diff --git a/coq/ethereum/__init__.ast b/coq/ethereum/__init__.ast new file mode 100644 index 0000000000..d77c250bcc --- /dev/null +++ b/coq/ethereum/__init__.ast @@ -0,0 +1,39 @@ +Module( + body=[ + Expr( + value=Constant(value="\n### Introduction\n\nSeeing as internet connections have been vastly expanding across the\nworld, spreading information has become as cheap as ever. Bitcoin, for\nexample, has demonstrated the possibility of creating a decentralized,\ntrade system that is accessible around the world. Namecoin is another\nsystem that built off of Bitcoin's currency structure to create other\nsimple technological applications.\n\nEthereum's goal is to create a cryptographically secure system in which\nany and all types of transaction-based concepts can be built. It provides\nan exceptionally accessible and decentralized system to build software\nand execute transactions.\n\nThis package contains a reference implementation, written as simply as\npossible, to aid in defining the behavior of Ethereum clients.\n")), + Import( + names=[ + alias(name='sys')]), + Assign( + targets=[ + Name(id='__version__', ctx=Store())], + value=Constant(value='0.1.0')), + Assign( + targets=[ + Name(id='EVM_RECURSION_LIMIT', ctx=Store())], + value=BinOp( + left=Constant(value=1024), + op=Mult(), + right=Constant(value=12))), + Expr( + value=Call( + func=Attribute( + value=Name(id='sys', ctx=Load()), + attr='setrecursionlimit', + ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='EVM_RECURSION_LIMIT', ctx=Load()), + Call( + func=Attribute( + value=Name(id='sys', ctx=Load()), + attr='getrecursionlimit', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/__init__.v b/coq/ethereum/__init__.v new file mode 100644 index 0000000000..d5e3c1fcff --- /dev/null +++ b/coq/ethereum/__init__.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +### Introduction + +Seeing as internet connections have been vastly expanding across the +world, spreading information has become as cheap as ever. Bitcoin, for +example, has demonstrated the possibility of creating a decentralized, +trade system that is accessible around the world. Namecoin is another +system that built off of Bitcoin's currency structure to create other +simple technological applications. + +Ethereum's goal is to create a cryptographically secure system in which +any and all types of transaction-based concepts can be built. It provides +an exceptionally accessible and decentralized system to build software +and execute transactions. + +This package contains a reference implementation, written as simply as +possible, to aid in defining the behavior of Ethereum clients. +*) + diff --git a/coq/ethereum/arrow_glacier/__init__.ast b/coq/ethereum/arrow_glacier/__init__.ast new file mode 100644 index 0000000000..87a471c0aa --- /dev/null +++ b/coq/ethereum/arrow_glacier/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe Arrow Glacier fork delays the difficulty bomb. There are no other changes\nin this fork.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=13773000)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/__init__.v b/coq/ethereum/arrow_glacier/__init__.v new file mode 100644 index 0000000000..4f971c997d --- /dev/null +++ b/coq/ethereum/arrow_glacier/__init__.v @@ -0,0 +1,7 @@ +(* Generated *) +(* +The Arrow Glacier fork delays the difficulty bomb. There are no other changes +in this fork. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/arrow_glacier/blocks.ast b/coq/ethereum/arrow_glacier/blocks.ast new file mode 100644 index 0000000000..06837ea5d6 --- /dev/null +++ b/coq/ethereum/arrow_glacier/blocks.ast @@ -0,0 +1,230 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='LegacyTransaction')], + level=1), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mix_digest', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='succeeded', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/blocks.v b/coq/ethereum/arrow_glacier/blocks.v new file mode 100644 index 0000000000..1bb452d42a --- /dev/null +++ b/coq/ethereum/arrow_glacier/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.arrow_glacier.fork_types. +Require ethereum.arrow_glacier.transactions. diff --git a/coq/ethereum/arrow_glacier/bloom.ast b/coq/ethereum/arrow_glacier/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/arrow_glacier/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/bloom.v b/coq/ethereum/arrow_glacier/bloom.v new file mode 100644 index 0000000000..2183f9ba63 --- /dev/null +++ b/coq/ethereum/arrow_glacier/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.arrow_glacier.blocks. +Require ethereum.arrow_glacier.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/exceptions.ast b/coq/ethereum/arrow_glacier/exceptions.ast new file mode 100644 index 0000000000..a61ee25448 --- /dev/null +++ b/coq/ethereum/arrow_glacier/exceptions.ast @@ -0,0 +1,72 @@ +Module( + body=[ + Expr( + value=Constant(value='\nExceptions specific to this fork.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Final')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidTransaction')], + level=0), + ClassDef( + name='TransactionTypeError', + bases=[ + Name(id='InvalidTransaction', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Unknown [EIP-2718] transaction type byte.\n\n [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718\n ')), + AnnAssign( + target=Name(id='transaction_type', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n The type byte of the transaction that caused the error.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='transaction_type', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='unknown transaction type `'), + FormattedValue( + value=Name(id='transaction_type', ctx=Load()), + conversion=-1), + Constant(value='`')])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='transaction_type', + ctx=Store())], + value=Name(id='transaction_type', ctx=Load()))], + decorator_list=[])], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/exceptions.v b/coq/ethereum/arrow_glacier/exceptions.v new file mode 100644 index 0000000000..9a313f6d0e --- /dev/null +++ b/coq/ethereum/arrow_glacier/exceptions.v @@ -0,0 +1,7 @@ +(* Generated *) +(* +Exceptions specific to this fork. +*) + +Require typing. +Require ethereum.exceptions. diff --git a/coq/ethereum/arrow_glacier/fork.ast b/coq/ethereum/arrow_glacier/fork.ast new file mode 100644 index 0000000000..6dd3262c01 --- /dev/null +++ b/coq/ethereum/arrow_glacier/fork.ast @@ -0,0 +1,3991 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.ethash', + names=[ + alias(name='dataset_size'), + alias(name='generate_cache'), + alias(name='hashimoto_light')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty'), + alias(name='create_ether'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_ACCESS_LIST_ADDRESS_COST'), + alias(name='TX_ACCESS_LIST_STORAGE_KEY_COST'), + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='AccessListTransaction'), + alias(name='FeeMarketTransaction'), + alias(name='LegacyTransaction'), + alias(name='Transaction'), + alias(name='decode_transaction'), + alias(name='encode_transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BLOCK_REWARD', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=18)))], + keywords=[])), + Assign( + targets=[ + Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='ELASTICITY_MULTIPLIER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=131072)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_OMMER_DEPTH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='BOMB_DELAY_BLOCKS', ctx=Store())], + value=Constant(value=10700000)), + Assign( + targets=[ + Name(id='EMPTY_OMMER_HASH', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List(elts=[], ctx=Load())], + keywords=[])], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='validate_ommers', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='chain', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='chain', ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_base_fee_per_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the base fee per gas for the block.\n\n Parameters\n ----------\n block_gas_limit :\n Gas limit of the block for which the base fee is being calculated.\n parent_gas_limit :\n Gas limit of the parent block.\n parent_gas_used :\n Gas used in the parent block.\n parent_base_fee_per_gas :\n Base fee per gas of the parent block.\n\n Returns\n -------\n base_fee_per_gas : `Uint`\n Base fee per gas for the block.\n ')), + Assign( + targets=[ + Name(id='parent_gas_target', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='ELASTICITY_MULTIPLIER', ctx=Load()))), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Name(id='block_gas_limit', ctx=Load()), + Name(id='parent_gas_limit', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='parent_gas_used', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='parent_gas_target', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=Name(id='parent_base_fee_per_gas', ctx=Load()))], + orelse=[ + If( + test=Compare( + left=Name(id='parent_gas_used', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='parent_gas_target', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='gas_used_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_used', ctx=Load()), + op=Sub(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='parent_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Mult(), + right=Name(id='gas_used_delta', ctx=Load()))), + Assign( + targets=[ + Name(id='target_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='base_fee_per_gas_delta', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=Name(id='target_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Load())), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Add(), + right=Name(id='base_fee_per_gas_delta', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='gas_used_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_target', ctx=Load()), + op=Sub(), + right=Name(id='parent_gas_used', ctx=Load()))), + Assign( + targets=[ + Name(id='parent_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Mult(), + right=Name(id='gas_used_delta', ctx=Load()))), + Assign( + targets=[ + Name(id='target_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='base_fee_per_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='target_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Load()))), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Sub(), + right=Name(id='base_fee_per_gas_delta', ctx=Load())))])]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='expected_base_fee_per_gas', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_base_fee_per_gas', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='expected_base_fee_per_gas', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='parent_has_ommers', ctx=Store())], + value=Compare( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='EMPTY_OMMER_HASH', ctx=Load())])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_difficulty', ctx=Store())], + value=Call( + func=Name(id='calculate_block_difficulty', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Name(id='parent_has_ommers', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_difficulty', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='validate_proof_of_work', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generate_header_hash_for_pow', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate rlp hash of the header which is to be used for Proof-of-Work\n verification.\n\n In other words, the PoW artefacts `mix_digest` and `nonce` are ignored\n while calculating this hash.\n\n A particular PoW is valid for a single hash, that hash is computed by\n this function. The `nonce` and `mix_digest` are omitted from this hash\n because they are being changed by miners in their search for a sufficient\n proof-of-work.\n\n Parameters\n ----------\n header :\n The header object for which the hash is to be generated.\n\n Returns\n -------\n hash : `Hash32`\n The PoW valid rlp hash of the passed in header.\n ')), + Assign( + targets=[ + Name(id='header_data_without_pow_artefacts', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='state_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='transactions_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='receipt_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='bloom', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='header_data_without_pow_artefacts', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='validate_proof_of_work', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the Proof of Work constraints.\n\n In order to verify that a miner's proof-of-work is valid for a block, a\n ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``\n hash function. The mix digest is a hash of the header and the nonce that\n is passed through and it confirms whether or not proof-of-work was done\n on the correct block. The result is the actual hash value of the block.\n\n Parameters\n ----------\n header :\n Header of interest.\n ")), + Assign( + targets=[ + Name(id='header_hash', ctx=Store())], + value=Call( + func=Name(id='generate_header_hash_for_pow', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache', ctx=Store())], + value=Call( + func=Name(id='generate_cache', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='mix_digest', ctx=Store()), + Name(id='result', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='hashimoto_light', ctx=Load()), + args=[ + Name(id='header_hash', ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + Name(id='cache', ctx=Load()), + Call( + func=Name(id='dataset_size', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='mix_digest', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='mix_digest', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='limit', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='limit', ctx=Load()), + op=FloorDiv(), + right=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n base_fee_per_gas :\n The block base fee.\n gas_available :\n The gas remaining in the block.\n chain_id :\n The ID of the current chain.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n effective_gas_price :\n The price to charge for gas when the transaction is executed.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='base_fee_per_gas', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='priority_fee_per_gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + op=Sub(), + right=Name(id='base_fee_per_gas', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='effective_gas_price', ctx=Store())], + value=BinOp( + left=Name(id='priority_fee_per_gas', ctx=Load()), + op=Add(), + right=Name(id='base_fee_per_gas', ctx=Load())))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='base_fee_per_gas', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='effective_gas_price', ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))]), + Return( + value=Tuple( + elts=[ + Name(id='sender_address', ctx=Load()), + Name(id='effective_gas_price', ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='error', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n error :\n Error in the top level frame of the transaction, if any.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='succeeded', + value=Compare( + left=Name(id='error', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)])), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='receipt', ctx=Load())], + keywords=[])))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='receipt', ctx=Load())], + keywords=[])))], + orelse=[ + Return( + value=Name(id='receipt', ctx=Load()))])])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Receipt', ctx=Load())], + ctx=Load()), + ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='block_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n base_fee_per_gas :\n Base fee per gas of within the block.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n block_difficulty :\n Difficulty of the block.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Receipt', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Call( + func=Name(id='map', ctx=Load()), + args=[ + Name(id='decode_transaction', ctx=Load()), + Name(id='transactions', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Call( + func=Name(id='encode_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='sender_address', ctx=Store()), + Name(id='effective_gas_price', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='base_fee_per_gas', ctx=Load()), + Name(id='gas_available', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='base_fee_per_gas', + value=Name(id='base_fee_per_gas', ctx=Load())), + keyword( + arg='gas_price', + value=Name(id='effective_gas_price', ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='difficulty', + value=Name(id='block_difficulty', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='chain_id', + value=Name(id='chain_id', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store()), + Name(id='error', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='error', ctx=Load()), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='pay_rewards', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='block_number', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='ommers', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='validate_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='block_header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the ommers mentioned in the block.\n\n An ommer block is a block that wasn't canonically added to the\n blockchain because it wasn't validated as fast as the canonical block\n but was mined at the same time.\n\n To be considered valid, the ommers must adhere to the rules defined in\n the Ethereum protocol. The maximum amount of ommers is 2 per block and\n there cannot be duplicate ommers in a block. Many of the other ommer\n constraints are listed in the in-line comments of this function.\n\n Parameters\n ----------\n ommers :\n List of ommers mentioned in the current block.\n block_header:\n The header of current block.\n chain :\n History and current state.\n ")), + Assign( + targets=[ + Name(id='block_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='block_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='ommers_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return()], + orelse=[]), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + op=Sub(), + right=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Name(id='ommer', ctx=Load()), + Name(id='ommer_parent_header', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=2)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommers_hashes', ctx=Store())], + value=ListComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + ifs=[], + is_async=0)])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[])], + keywords=[])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_canonical_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=BinOp( + left=Name(id='MAX_OMMER_DEPTH', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + ctx=Load())), + Assign( + targets=[ + Name(id='recent_canonical_block_hashes', ctx=Store())], + value=SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='recent_ommers_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + simple=1), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='recent_ommers_hashes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='recent_ommers_hashes', ctx=Load()), + attr='union', + ctx=Load()), + args=[ + SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='ommer_index', ctx=Store()), + Name(id='ommer', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='ommer_hash', ctx=Store())], + value=Subscript( + value=Name(id='ommers_hashes', ctx=Load()), + slice=Name(id='ommer_index', ctx=Load()), + ctx=Load())), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='block_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_ommers_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='ommer_age', ctx=Load())]), + Compare( + left=Name(id='ommer_age', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_OMMER_DEPTH', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='parent_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pay_rewards', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pay rewards to the block miner as well as the ommers miners.\n\n The miner of the canonical block is rewarded with the predetermined\n block reward, ``BLOCK_REWARD``, plus a variable award based off of the\n number of ommer blocks that were mined around the same time, and included\n in the canonical block's header. An ommer block is a block that wasn't\n added to the canonical blockchain because it wasn't validated as fast as\n the accepted block but was mined at the same time. Although not all blocks\n that are mined are added to the canonical chain, miners are still paid a\n reward for their efforts. This reward is called an ommer reward and is\n calculated based on the number associated with the ommer block that they\n mined.\n\n Parameters\n ----------\n state :\n Current account state.\n block_number :\n Position of the block within the chain.\n coinbase :\n Address of account which receives block reward and transaction fees.\n ommers :\n List of ommers mentioned in the current block.\n ")), + Assign( + targets=[ + Name(id='ommer_count', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='miner_reward', ctx=Store())], + value=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='ommer_count', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='miner_reward', ctx=Load())], + keywords=[])), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_number', ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='ommer_miner_reward', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Sub(), + right=Name(id='ommer_age', ctx=Load())), + op=Mult(), + right=Name(id='BLOCK_REWARD', ctx=Load())), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='ommer_miner_reward', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + AnnAssign( + target=Name(id='max_gas_fee', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='max_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load())], + keywords=[])))], + orelse=[ + Assign( + targets=[ + Name(id='max_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])))]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='max_gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='effective_gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='effective_gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='preaccessed_addresses', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='preaccessed_storage_keys', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Tuple( + elts=[ + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='address', ctx=Store()), + Name(id='keys', ctx=Store())], + ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='keys', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_storage_keys', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Name(id='address', ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[ + keyword( + arg='preaccessed_addresses', + value=Call( + func=Name(id='frozenset', ctx=Load()), + args=[ + Name(id='preaccessed_addresses', ctx=Load())], + keywords=[])), + keyword( + arg='preaccessed_storage_keys', + value=Call( + func=Name(id='frozenset', ctx=Load()), + args=[ + Name(id='preaccessed_storage_keys', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='priority_fee_per_gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Name(id='priority_fee_per_gas', ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + If( + test=Compare( + left=Name(id='coinbase_balance_after_mining_fee', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]))], + orelse=[])]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='error', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Name(id='TX_CREATE_COST', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Assign( + targets=[ + Name(id='access_list_cost', ctx=Store())], + value=Constant(value=0)), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Tuple( + elts=[ + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='_address', ctx=Store()), + Name(id='keys', ctx=Store())], + ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + body=[ + AugAssign( + target=Name(id='access_list_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_ACCESS_LIST_ADDRESS_COST', ctx=Load())), + AugAssign( + target=Name(id='access_list_cost', ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='keys', ctx=Load())], + keywords=[]), + op=Mult(), + right=Name(id='TX_ACCESS_LIST_STORAGE_KEY_COST', ctx=Load())))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load())), + op=Add(), + right=Name(id='access_list_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=28)])]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash_pre155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='chain_id_x2', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=36)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[])), + op=Sub(), + right=Name(id='chain_id_x2', ctx=Load())), + Call( + func=Name(id='signing_hash_155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])], + keywords=[]))])], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='y_parity', + ctx=Load()), + Call( + func=Name(id='signing_hash_2930', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='y_parity', + ctx=Load()), + Call( + func=Name(id='signing_hash_1559', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])])]), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash_pre155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='LegacyTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a legacy (pre EIP 155) signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='LegacyTransaction', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 155 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n The id of the current chain.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='chain_id', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_2930', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='AccessListTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 2930 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load())], + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_1559', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='FeeMarketTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 1559 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load())], + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_has_ommers', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes difficulty of a block using its header and parent header.\n\n The difficulty is determined by the time the block was created after its\n parent. The ``offset`` is calculated using the parent block's difficulty,\n ``parent_difficulty``, and the timestamp between blocks. This offset is\n then added to the parent difficulty and is stored as the ``difficulty``\n variable. If the time between the block and its parent is too short, the\n offset will result in a positive number thus making the sum of\n ``parent_difficulty`` and ``offset`` to be a greater value in order to\n avoid mass forking. But, if the time is long enough, then the offset\n results in a negative value making the block less difficult than\n its parent.\n\n The base standard for a block's difficulty is the predefined value\n set for the genesis block since it has no parent. So, a block\n can't be less difficult than the genesis block, therefore each block's\n difficulty is set to the maximum value between the calculated\n difficulty and the ``GENESIS_DIFFICULTY``.\n\n Parameters\n ----------\n block_number :\n Block number of the block.\n block_timestamp :\n Timestamp of the block.\n parent_timestamp :\n Timestamp of the parent block.\n parent_difficulty :\n difficulty of the parent block.\n parent_has_ommers:\n does the parent have ommers.\n\n Returns\n -------\n difficulty : `ethereum.base_types.Uint`\n Computed difficulty for a block.\n ")), + Assign( + targets=[ + Name(id='offset', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=2048)), + op=Mult(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=IfExp( + test=Name(id='parent_has_ommers', ctx=Load()), + body=Constant(value=2), + orelse=Constant(value=1)), + op=Sub(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_timestamp', ctx=Load()), + op=Sub(), + right=Name(id='parent_timestamp', ctx=Load()))], + keywords=[]), + op=FloorDiv(), + right=Constant(value=9))), + UnaryOp( + op=USub(), + operand=Constant(value=99))], + keywords=[]))), + Assign( + targets=[ + Name(id='difficulty', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='offset', ctx=Load()))), + Assign( + targets=[ + Name(id='num_bomb_periods', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='BOMB_DELAY_BLOCKS', ctx=Load())), + op=FloorDiv(), + right=Constant(value=100000)), + op=Sub(), + right=Constant(value=2))), + If( + test=Compare( + left=Name(id='num_bomb_periods', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='difficulty', ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Name(id='num_bomb_periods', ctx=Load())))], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='difficulty', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/fork.v b/coq/ethereum/arrow_glacier/fork.v new file mode 100644 index 0000000000..bb6c6a0dd8 --- /dev/null +++ b/coq/ethereum/arrow_glacier/fork.v @@ -0,0 +1,946 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.ethash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.arrow_glacier.__init__. +Require ethereum.arrow_glacier.blocks. +Require ethereum.arrow_glacier.bloom. +Require ethereum.arrow_glacier.fork_types. +Require ethereum.arrow_glacier.state. +Require ethereum.arrow_glacier.transactions. +Require ethereum.arrow_glacier.trie. +Require ethereum.arrow_glacier.utils.message. +Require ethereum.arrow_glacier.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + do* [[ M.get_local ~(| "validate_ommers" |) ~(| + M.get_field ~(| block, "ommers" |), + M.get_field ~(| block, "header" |), + chain + |) ]] in + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "base_fee_per_gas" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "difficulty" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| block, "ommers" |), + M.get_field ~(| chain, "chain_id" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_base_fee_per_gas (block_gas_limit : Uint) (parent_gas_limit : Uint) (parent_gas_used : Uint) (parent_base_fee_per_gas : Uint) : M Uint := + (* + 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. + *) + do* M.assign "parent_gas_target" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + (* TODO statement *) + do* M.assign "expected_base_fee_per_gas" [[ + M.get_local ~(| "calculate_base_fee_per_gas" |) ~(| + M.get_field ~(| header, "gas_limit" |), + M.get_field ~(| parent_header, "gas_limit" |), + M.get_field ~(| parent_header, "gas_used" |), + M.get_field ~(| parent_header, "base_fee_per_gas" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "parent_has_ommers" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_difficulty" [[ + M.get_local ~(| "calculate_block_difficulty" |) ~(| + M.get_field ~(| header, "number" |), + M.get_field ~(| header, "timestamp" |), + M.get_field ~(| parent_header, "timestamp" |), + M.get_field ~(| parent_header, "difficulty" |), + M.get_local ~(| "parent_has_ommers" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| + header + |) ]] in + M.pure tt. + +Definition generate_header_hash_for_pow (header : Header) : M Hash32 := + (* + 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. + *) + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_proof_of_work (header : Header) : M unit := + (* + 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. + *) + do* M.assign "header_hash" [[ + M.get_local ~(| "generate_header_hash_for_pow" |) ~(| + header + |) in + ]] in + do* M.assign "cache" [[ + ethereum.ethash.generate_cache ~(| + M.get_field ~(| header, "number" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (base_fee_per_gas : Uint) (gas_available : Uint) (chain_id : U64) : M (* TODO type *) := + (* + 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. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (error : (* TODO type *)) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (base_fee_per_gas : Uint) (block_gas_limit : Uint) (block_time : U256) (block_difficulty : Uint) (transactions : (* TODO type *)) (ommers : (* TODO type *)) (chain_id : U64) : M ApplyBodyOutput := + (* + 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 + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "pay_rewards" |) ~(| + state, + block_number, + coinbase, + ommers + |) ]] in + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_ommers (ommers : (* TODO type *)) (block_header : Header) (chain : BlockChain) : M unit := + (* + 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. + *) + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_canonical_blocks" [[ + (* TODO expression *) in + ]] in + do* M.assign "recent_canonical_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition pay_rewards (state : State) (block_number : Uint) (coinbase : Address) (ommers : (* TODO type *)) : M unit := + (* + 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. + *) + do* M.assign "ommer_count" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + ommers + |) + |) in + ]] in + do* M.assign "miner_reward" [[ + (* TODO expression *) in + ]] in + do* [[ state.create_ether ~(| + state, + coinbase, + M.get_local ~(| "miner_reward" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "effective_gas_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "preaccessed_addresses" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "preaccessed_storage_keys" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + (* TODO statement *) + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "priority_fee_per_gas" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "access_list_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_pre155 (tx : LegacyTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_155 (tx : LegacyTransaction) (chain_id : U64) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_2930 (tx : AccessListTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_1559 (tx : FeeMarketTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_block_difficulty (block_number : Uint) (block_timestamp : U256) (parent_timestamp : U256) (parent_difficulty : Uint) (parent_has_ommers : bool) : M Uint := + (* + 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. + *) + do* M.assign "offset" [[ + (* TODO expression *) in + ]] in + do* M.assign "difficulty" [[ + (* TODO expression *) in + ]] in + do* M.assign "num_bomb_periods" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/fork_types.ast b/coq/ethereum/arrow_glacier/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/arrow_glacier/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/fork_types.v b/coq/ethereum/arrow_glacier/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/arrow_glacier/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/state.ast b/coq/ethereum/arrow_glacier/state.ast new file mode 100644 index 0000000000..c04909fdce --- /dev/null +++ b/coq/ethereum/arrow_glacier/state.ast @@ -0,0 +1,1692 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='created_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='set', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mark_account_created', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Mark an account as having been created in the current transaction.\n This information is used by `get_storage_original()` to handle an obscure\n edgecase.\n\n The marker is not removed even if the account creation reverts. Since the\n account cannot have had code prior to its creation and can't call\n `get_storage_original()`, this is harmless.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account that has been created.\n ")), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has zero nonce, empty code and zero balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_empty : `bool`\n True if if an account has zero nonce, empty code and zero balance,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_exists_and_is_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists and has zero nonce, empty code and zero\n balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n exists_and_is_empty : `bool`\n True if an account exists and has zero nonce, empty code and zero\n balance, False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='account', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_alive', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether is an account is both in the state and non empty.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_alive : `bool`\n True if the account is alive.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[ + Return( + value=UnaryOp( + op=Not(), + operand=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])])))])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add newly created ether to an account.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to which ether is added.\n amount:\n The amount of ether to be added to the account of interest.\n ')), + FunctionDef( + name='increase_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage_original', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the original value in a storage slot i.e. the value before the current\n transaction began. This function reads the value from the snapshots taken\n before executing the transaction.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to read the value from.\n key:\n Key of the storage slot.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='_', ctx=Store()), + Name(id='original_trie', ctx=Store())], + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + Assign( + targets=[ + Name(id='original_account_trie', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='original_trie', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='original_account_trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='original_account_trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[]))]), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='original_value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='original_value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/state.v b/coq/ethereum/arrow_glacier/state.v new file mode 100644 index 0000000000..1cde4ff47c --- /dev/null +++ b/coq/ethereum/arrow_glacier/state.v @@ -0,0 +1,614 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.arrow_glacier.fork_types. +Require ethereum.arrow_glacier.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition mark_account_created (state : State) (address : Address) : M unit := + (* + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| + address + |) ]] in + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_empty (state : State) (address : Address) : M bool := + (* + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition account_exists_and_is_empty (state : State) (address : Address) : M bool := + (* + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_alive (state : State) (address : Address) : M bool := + (* + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := + (* + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. + +Definition get_storage_original (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + *) + (* TODO statement *) + (* TODO assignment *) + do* M.assign "original_account_trie" [[ + M.get_field ~(| M.get_local ~(| "original_trie" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/transactions.ast b/coq/ethereum/arrow_glacier/transactions.ast new file mode 100644 index 0000000000..264b048f3f --- /dev/null +++ b/coq/ethereum/arrow_glacier/transactions.ast @@ -0,0 +1,492 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='TransactionTypeError')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + Assign( + targets=[ + Name(id='TX_ACCESS_LIST_ADDRESS_COST', ctx=Store())], + value=Constant(value=2400)), + Assign( + targets=[ + Name(id='TX_ACCESS_LIST_STORAGE_KEY_COST', ctx=Store())], + value=Constant(value=1900)), + ClassDef( + name='LegacyTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='AccessListTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The transaction type added in EIP-2930 to support access lists.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='access_list', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y_parity', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='FeeMarketTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The transaction type added in EIP-1559.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_priority_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='access_list', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y_parity', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='Transaction', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Encode a transaction. Needed because non-legacy transactions aren't RLP.\n ")), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='tx', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])))], + orelse=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Unable to encode transaction of type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + conversion=-1)])], + keywords=[]))])])])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='decode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Decode a transaction. Needed because non-legacy transactions aren't RLP.\n ")), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Name(id='AccessListTransaction', ctx=Load()), + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=2)]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Name(id='FeeMarketTransaction', ctx=Load()), + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())], + keywords=[]))], + orelse=[ + Raise( + exc=Call( + func=Name(id='TransactionTypeError', ctx=Load()), + args=[ + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]))])])], + orelse=[ + Return( + value=Name(id='tx', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Transaction', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/transactions.v b/coq/ethereum/arrow_glacier/transactions.v new file mode 100644 index 0000000000..2d3c2e5941 --- /dev/null +++ b/coq/ethereum/arrow_glacier/transactions.v @@ -0,0 +1,29 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.arrow_glacier.exceptions. +Require ethereum.arrow_glacier.fork_types. + +Definition encode_transaction (tx : Transaction) : M (* TODO type *) := + (* + Encode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + M.pure tt. + +Definition decode_transaction (tx : (* TODO type *)) : M Transaction := + (* + Decode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/trie.ast b/coq/ethereum/arrow_glacier/trie.ast new file mode 100644 index 0000000000..b6116730d8 --- /dev/null +++ b/coq/ethereum/arrow_glacier/trie.ast @@ -0,0 +1,1632 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.london', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='LegacyTransaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Receipt', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.RLP`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/trie.v b/coq/ethereum/arrow_glacier/trie.v new file mode 100644 index 0000000000..6b8953f256 --- /dev/null +++ b/coq/ethereum/arrow_glacier/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/utils/__init__.ast b/coq/ethereum/arrow_glacier/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/arrow_glacier/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/utils/__init__.v b/coq/ethereum/arrow_glacier/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/arrow_glacier/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/arrow_glacier/utils/address.ast b/coq/ethereum/arrow_glacier/utils/address.ast new file mode 100644 index 0000000000..451bdf6ea5 --- /dev/null +++ b/coq/ethereum/arrow_glacier/utils/address.ast @@ -0,0 +1,216 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this arrow_glacier version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_create2_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='salt', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='call_data', + annotation=Name(id='bytearray', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created, which is\n based on the sender address, salt and the call data as well.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n salt :\n Address generation salt.\n call_data :\n The code of the new account which is to be created.\n\n Returns\n -------\n address: `ethereum.arrow_glacier.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='preimage', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Constant(value=b'\xff'), + op=Add(), + right=Name(id='address', ctx=Load())), + op=Add(), + right=Name(id='salt', ctx=Load())), + op=Add(), + right=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='call_data', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/utils/address.v b/coq/ethereum/arrow_glacier/utils/address.v new file mode 100644 index 0000000000..4fc0d539ed --- /dev/null +++ b/coq/ethereum/arrow_glacier/utils/address.v @@ -0,0 +1,115 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this arrow_glacier version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.arrow_glacier.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition compute_create2_contract_address (address : Address) (salt : Bytes32) (call_data : bytearray) : M Address := + (* + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.arrow_glacier.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "preimage" [[ + (* TODO expression *) in + ]] in + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "preimage" |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/utils/hexadecimal.ast b/coq/ethereum/arrow_glacier/utils/hexadecimal.ast new file mode 100644 index 0000000000..b7e62054fe --- /dev/null +++ b/coq/ethereum/arrow_glacier/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to\nArrow Glacier types.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/utils/hexadecimal.v b/coq/ethereum/arrow_glacier/utils/hexadecimal.v new file mode 100644 index 0000000000..ea593a7f88 --- /dev/null +++ b/coq/ethereum/arrow_glacier/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Arrow Glacier types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.arrow_glacier.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/utils/message.ast b/coq/ethereum/arrow_glacier/utils/message.ast new file mode 100644 index 0000000000..d34d6c6cc1 --- /dev/null +++ b/coq/ethereum/arrow_glacier/utils/message.ast @@ -0,0 +1,335 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this arrow_glacier version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='FrozenSet'), + alias(name='Optional'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_static', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='preaccessed_addresses', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='preaccessed_storage_keys', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True), + Constant(value=False), + Call( + func=Name(id='frozenset', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='frozenset', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n is_static:\n if True then it prevents all state-changing operations from being\n executed.\n preaccessed_addresses:\n Addresses that should be marked as accessed prior to the message call\n preaccessed_storage_keys:\n Storage keys that should be marked as accessed prior to the message\n call\n\n Returns\n -------\n message: `ethereum.arrow_glacier.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Assign( + targets=[ + Name(id='accessed_addresses', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='current_target', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='caller', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Name(id='preaccessed_addresses', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=Name(id='is_static', ctx=Load())), + keyword( + arg='accessed_addresses', + value=Name(id='accessed_addresses', ctx=Load())), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='preaccessed_storage_keys', ctx=Load())], + keywords=[])), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/utils/message.v b/coq/ethereum/arrow_glacier/utils/message.v new file mode 100644 index 0000000000..46eb905f41 --- /dev/null +++ b/coq/ethereum/arrow_glacier/utils/message.v @@ -0,0 +1,85 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this arrow_glacier version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.arrow_glacier.fork_types. +Require ethereum.arrow_glacier.state. +Require ethereum.arrow_glacier.vm. +Require ethereum.arrow_glacier.vm.precompiled_contracts.mapping. +Require ethereum.arrow_glacier.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) (is_static : bool) (preaccessed_addresses : (* TODO type *)) (preaccessed_storage_keys : (* TODO type *)) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.arrow_glacier.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + do* M.assign "accessed_addresses" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "add" |) ~(| + M.get_local ~(| "current_target" |) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "add" |) ~(| + caller + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS, "keys" |) ~(| + + |) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + preaccessed_addresses + |) ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/__init__.ast b/coq/ethereum/arrow_glacier/vm/__init__.ast new file mode 100644 index 0000000000..5290882162 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/__init__.ast @@ -0,0 +1,591 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty')], + level=2), + ImportFrom( + module='precompiled_contracts', + names=[ + alias(name='RIPEMD160_ADDRESS')], + level=1), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='is_static', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_addresses', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_storage_keys', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='return_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_addresses', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_storage_keys', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + If( + test=Compare( + left=Name(id='RIPEMD160_ADDRESS', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/__init__.v b/coq/ethereum/arrow_glacier/vm/__init__.v new file mode 100644 index 0000000000..c9ac2fbb9d --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/__init__.v @@ -0,0 +1,78 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.arrow_glacier.blocks. +Require ethereum.arrow_glacier.fork_types. +Require ethereum.arrow_glacier.state. +Require ethereum.arrow_glacier.vm.precompiled_contracts. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "touched_accounts" |), "update" |) ~(| + M.get_field ~(| child_evm, "touched_accounts" |) + |) ]] in + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| child_evm, "accessed_addresses" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_storage_keys" |), "update" |) ~(| + M.get_field ~(| child_evm, "accessed_storage_keys" |) + |) ]] in + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + (* TODO statement *) + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/exceptions.ast b/coq/ethereum/arrow_glacier/vm/exceptions.ast new file mode 100644 index 0000000000..79ecb4b47d --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/exceptions.ast @@ -0,0 +1,175 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='Revert', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised by the `REVERT` opcode.\n\n Unlike other EVM exceptions this does not result in the consumption of all\n gas.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='WriteInStaticContext', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt is made to modify the state while operating inside\n of a STATICCALL context.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfBoundsRead', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt was made to read data beyond the\n boundaries of the buffer.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidParameter', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when invalid parameters are passed.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidContractPrefix', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract code starts with 0xEF.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/exceptions.v b/coq/ethereum/arrow_glacier/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/arrow_glacier/vm/gas.ast b/coq/ethereum/arrow_glacier/vm/gas.ast new file mode 100644 index 0000000000..33b4cae82f --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/gas.ast @@ -0,0 +1,813 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=4800)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RETURN_DATA_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_FAST_STEP', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLAKE2_PER_ROUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COLD_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2100)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_WARM_ACCESS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=100)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_left', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='memory_cost', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='extra_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='call_stipend', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Expr( + value=Constant(value='\n Calculates the MessageCallGas (cost and stipend) for\n executing call Opcodes.\n\n Parameters\n ----------\n value:\n The amount of `ETH` that needs to be transferred.\n gas :\n The amount of gas provided to the message-call.\n gas_left :\n The amount of gas left in the current frame.\n memory_cost :\n The amount needed to extend the memory in the current frame.\n extra_gas :\n The amount of gas needed for transferring value + creating a new\n account inside a message call.\n call_stipend :\n The amount of stipend provided to a message call to execute code while\n transferring value(ETH).\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='call_stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='call_stipend', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='extra_gas', ctx=Load()), + op=Add(), + right=Name(id='memory_cost', ctx=Load()))]), + body=[ + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='gas', ctx=Load()), + Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='gas_left', ctx=Load()), + op=Sub(), + right=Name(id='memory_cost', ctx=Load())), + op=Sub(), + right=Name(id='extra_gas', ctx=Load()))], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load())), + FunctionDef( + name='max_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the maximum gas that is allowed for making a message call\n\n Parameters\n ----------\n gas :\n The amount of gas provided to the message-call.\n\n Returns\n -------\n max_allowed_message_call_gas: `ethereum.base_types.Uint`\n The maximum gas allowed for making the message-call.\n ')), + Return( + value=BinOp( + left=Name(id='gas', ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='gas', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]))))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/gas.v b/coq/ethereum/arrow_glacier/vm/gas.v new file mode 100644 index 0000000000..5038c7bae4 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/gas.v @@ -0,0 +1,171 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (value : U256) (gas : Uint) (gas_left : Uint) (memory_cost : Uint) (extra_gas : Uint) (call_stipend : Uint) : M MessageCallGas := + (* + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "gas" [[ + M.get_local ~(| "min" |) ~(| + gas, + M.get_local ~(| "max_message_call_gas" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition max_message_call_gas (gas : Uint) : M Uint := + (* + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/instructions/__init__.ast b/coq/ethereum/arrow_glacier/vm/instructions/__init__.ast new file mode 100644 index 0000000000..5dae83fbf2 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/__init__.ast @@ -0,0 +1,1792 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='SHL', ctx=Store())], + value=Constant(value=27)), + Assign( + targets=[ + Name(id='SHR', ctx=Store())], + value=Constant(value=28)), + Assign( + targets=[ + Name(id='SAR', ctx=Store())], + value=Constant(value=29)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='RETURNDATASIZE', ctx=Store())], + value=Constant(value=61)), + Assign( + targets=[ + Name(id='RETURNDATACOPY', ctx=Store())], + value=Constant(value=62)), + Assign( + targets=[ + Name(id='EXTCODEHASH', ctx=Store())], + value=Constant(value=63)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='DIFFICULTY', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='CHAINID', ctx=Store())], + value=Constant(value=70)), + Assign( + targets=[ + Name(id='SELFBALANCE', ctx=Store())], + value=Constant(value=71)), + Assign( + targets=[ + Name(id='BASEFEE', ctx=Store())], + value=Constant(value=72)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='CREATE2', ctx=Store())], + value=Constant(value=245)), + Assign( + targets=[ + Name(id='STATICCALL', ctx=Store())], + value=Constant(value=250)), + Assign( + targets=[ + Name(id='REVERT', ctx=Store())], + value=Constant(value=253)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SAR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIFFICULTY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CHAINID', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODEHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFBALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BASEFEE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STATICCALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='REVERT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE2', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shl', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shr', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_sar', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodehash', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='self_balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='base_fee', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='staticcall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='revert', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create2', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/instructions/__init__.v b/coq/ethereum/arrow_glacier/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/arrow_glacier/vm/instructions/arithmetic.ast b/coq/ethereum/arrow_glacier/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/instructions/arithmetic.v b/coq/ethereum/arrow_glacier/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..26812429f1 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/instructions/bitwise.ast b/coq/ethereum/arrow_glacier/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..b72397f0ec --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/bitwise.ast @@ -0,0 +1,751 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shl', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift left (SHL) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='value', ctx=Load()), + op=LShift(), + right=Name(id='shift', ctx=Load())), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]))], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shr', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift right (SHR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_sar', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Arithmetic shift right (SAR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='signed_value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=256)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + BinOp( + left=Name(id='signed_value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load()))], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='signed_value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load()))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/instructions/bitwise.v b/coq/ethereum/arrow_glacier/vm/instructions/bitwise.v new file mode 100644 index 0000000000..c5088ce92a --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/bitwise.v @@ -0,0 +1,309 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shl (evm : Evm) : M unit := + (* + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shr (evm : Evm) : M unit := + (* + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_sar (evm : Evm) : M unit := + (* + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + M.get_local ~(| "int" |) ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "signed_value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/instructions/block.ast b/coq/ethereum/arrow_glacier/vm/instructions/block.ast new file mode 100644 index 0000000000..b9ccb3290b --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/block.ast @@ -0,0 +1,492 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's difficulty onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='chain_id', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the chain id onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/instructions/block.v b/coq/ethereum/arrow_glacier/vm/instructions/block.v new file mode 100644 index 0000000000..4fc1907bac --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/block.v @@ -0,0 +1,241 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition difficulty (evm : Evm) : M unit := + (* + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition chain_id (evm : Evm) : M unit := + (* + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/instructions/comparison.ast b/coq/ethereum/arrow_glacier/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/instructions/comparison.v b/coq/ethereum/arrow_glacier/vm/instructions/comparison.v new file mode 100644 index 0000000000..0e05bb361b --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/instructions/control_flow.ast b/coq/ethereum/arrow_glacier/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/instructions/control_flow.v b/coq/ethereum/arrow_glacier/vm/instructions/control_flow.v new file mode 100644 index 0000000000..17c2e4cf05 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.exceptions. +Require ethereum.arrow_glacier.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/instructions/environment.ast b/coq/ethereum/arrow_glacier/vm/instructions/environment.ast new file mode 100644 index 0000000000..60bbfdaff1 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/environment.ast @@ -0,0 +1,1828 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfBoundsRead')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_COLD_ACCOUNT_ACCESS'), + alias(name='GAS_COPY'), + alias(name='GAS_FAST_STEP'), + alias(name='GAS_RETURN_DATA_COPY'), + alias(name='GAS_VERY_LOW'), + alias(name='GAS_WARM_ACCESS'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_WARM_ACCESS', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the size of the return data buffer onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copies data from the return data buffer code to memory\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='return_data_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_RETURN_DATA_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='return_data_start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfBoundsRead', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load()), + slice=Slice( + lower=Name(id='return_data_start_position', ctx=Load()), + upper=BinOp( + left=Name(id='return_data_start_position', ctx=Load()), + op=Add(), + right=Name(id='size', ctx=Load()))), + ctx=Load())), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodehash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns the keccak256 hash of a contract’s bytecode\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='EMPTY_ACCOUNT', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codehash', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='self_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the current address to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_FAST_STEP', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='base_fee', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the base fee of the current block on to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/instructions/environment.v b/coq/ethereum/arrow_glacier/vm/instructions/environment.v new file mode 100644 index 0000000000..fc896dbe4a --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/environment.v @@ -0,0 +1,728 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.arrow_glacier.fork_types. +Require ethereum.arrow_glacier.state. +Require ethereum.arrow_glacier.utils.address. +Require ethereum.arrow_glacier.vm.memory. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.exceptions. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatasize (evm : Evm) : M unit := + (* + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatacopy (evm : Evm) : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "return_data_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + (* TODO expression *) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodehash (evm : Evm) : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "account" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codehash" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition self_balance (evm : Evm) : M unit := + (* + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_FAST_STEP + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition base_fee (evm : Evm) : M unit := + (* + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "base_fee_per_gas" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/instructions/keccak.ast b/coq/ethereum/arrow_glacier/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/instructions/keccak.v b/coq/ethereum/arrow_glacier/vm/instructions/keccak.v new file mode 100644 index 0000000000..af472a7dc1 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.memory. +Require ethereum.arrow_glacier.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/instructions/log.ast b/coq/ethereum/arrow_glacier/vm/instructions/log.ast new file mode 100644 index 0000000000..0ded0e04ba --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/log.ast @@ -0,0 +1,323 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/instructions/log.v b/coq/ethereum/arrow_glacier/vm/instructions/log.v new file mode 100644 index 0000000000..65b0c921c8 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/log.v @@ -0,0 +1,79 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.arrow_glacier.blocks. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.exceptions. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.memory. +Require ethereum.arrow_glacier.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO statement *) + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/instructions/memory.ast b/coq/ethereum/arrow_glacier/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/instructions/memory.v b/coq/ethereum/arrow_glacier/vm/instructions/memory.v new file mode 100644 index 0000000000..9cc059ed5b --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.memory. +Require ethereum.arrow_glacier.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/instructions/stack.ast b/coq/ethereum/arrow_glacier/vm/instructions/stack.ast new file mode 100644 index 0000000000..95cfc0b6cf --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/stack.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/instructions/stack.v b/coq/ethereum/arrow_glacier/vm/instructions/stack.v new file mode 100644 index 0000000000..201a93d910 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/stack.v @@ -0,0 +1,153 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.exceptions. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/instructions/storage.ast b/coq/ethereum/arrow_glacier/vm/instructions/storage.ast new file mode 100644 index 0000000000..68640a90a8 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/storage.ast @@ -0,0 +1,551 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='get_storage_original'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_STIPEND'), + alias(name='GAS_COLD_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='GAS_WARM_ACCESS'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_SLOAD', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='get_storage_original', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + If( + test=Compare( + left=Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_COLD_SLOAD', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='current_value', ctx=Load())]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())])]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_COLD_SLOAD', ctx=Load())))])], + orelse=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))]), + If( + test=Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='GAS_STORAGE_SET', ctx=Load()), + op=Sub(), + right=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + keywords=[]))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_COLD_SLOAD', ctx=Load())), + op=Sub(), + right=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + keywords=[]))])], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/instructions/storage.v b/coq/ethereum/arrow_glacier/vm/instructions/storage.v new file mode 100644 index 0000000000..b1054ff0ff --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/storage.v @@ -0,0 +1,121 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.arrow_glacier.state. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.exceptions. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "original_value" [[ + state.get_storage_original ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "gas_cost" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/instructions/system.ast b/coq/ethereum/arrow_glacier/vm/instructions/system.ast new file mode 100644 index 0000000000..0fcb1135df --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/system.ast @@ -0,0 +1,2897 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='is_account_alive'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='compute_create2_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='Revert'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_VALUE'), + alias(name='GAS_COLD_ACCOUNT_ACCESS'), + alias(name='GAS_CREATE'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='GAS_NEW_ACCOUNT'), + alias(name='GAS_SELF_DESTRUCT'), + alias(name='GAS_SELF_DESTRUCT_NEW_ACCOUNT'), + alias(name='GAS_WARM_ACCESS'), + alias(name='GAS_ZERO'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas'), + alias(name='max_message_call_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='generic_create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='endowment', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='contract_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='memory_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Core logic used by the `CREATE*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='contract_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='create_message_gas', ctx=Load())), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='is_static', + value=Constant(value=False)), + keyword( + arg='accessed_addresses', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create2', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Creates a new account with associated code.\n\n It's similar to CREATE opcode except that the address of new account\n depends on the init_code instead of the nonce of sender.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ")), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='salt', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='call_data_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='call_data_words', ctx=Load()))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_create2_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='salt', ctx=Load()), + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_staticcall', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=IfExp( + test=Name(id='is_staticcall', ctx=Load()), + body=Constant(value=True), + orelse=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()))), + keyword( + arg='accessed_addresses', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='to', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=BoolOp( + op=Or(), + values=[ + Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[]), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='access_gas_cost', ctx=Load()), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='code_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=Name(id='access_gas_cost', ctx=Load()), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SELF_DESTRUCT', ctx=Load())), + If( + test=Compare( + left=Name(id='beneficiary', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[])), + Compare( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='code_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='access_gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='staticcall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='to', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='access_gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='revert', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop execution and revert state changes, without consuming all provided gas\n and also has the ability to return a reason\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Name(id='output', ctx=Load())], + keywords=[])), + Raise( + exc=Name(id='Revert', ctx=Load())), + Pass()], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/instructions/system.v b/coq/ethereum/arrow_glacier/vm/instructions/system.v new file mode 100644 index 0000000000..d00e517b01 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/instructions/system.v @@ -0,0 +1,779 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.arrow_glacier.fork_types. +Require ethereum.arrow_glacier.state. +Require ethereum.arrow_glacier.utils.address. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.exceptions. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.memory. +Require ethereum.arrow_glacier.vm.stack. + +Definition generic_create (evm : Evm) (endowment : U256) (contract_address : Address) (memory_start_position : U256) (memory_size : U256) : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "add" |) ~(| + contract_address + |) ]] in + do* M.assign "create_message_gas" [[ + gas.max_message_call_gas ~(| + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) in + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_local ~(| "create_message_gas" |) + ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_start_position, + memory_size + |) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_create_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition create2 (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "salt" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "call_data_words" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_create2_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "salt" |), + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (is_staticcall : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_SELF_DESTRUCT in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + M.get_local ~(| "access_gas_cost" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition staticcall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + M.get_local ~(| "access_gas_cost" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "to" |), + M.get_local ~(| "to" |), + True, + True, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition revert (evm : Evm) : M unit := + (* + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "output" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/interpreter.ast b/coq/ethereum/arrow_glacier/vm/interpreter.ast new file mode 100644 index 0000000000..6411a26545 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/interpreter.ast @@ -0,0 +1,1177 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Iterable'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='increment_nonce'), + alias(name='mark_account_created'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidContractPrefix'), + alias(name='InvalidOpcode'), + alias(name='OutOfGasError'), + alias(name='Revert'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_CODE_SIZE', ctx=Store())], + value=Constant(value=24576)), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `touched_accounts`: Accounts that have been touched.\n 6. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='touched_accounts', + value=Name(id='touched_accounts', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.london.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='mark_account_created', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='contract_code', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=239)]), + body=[ + Raise( + exc=Name(id='InvalidContractPrefix', ctx=Load()))], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_CODE_SIZE', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.london.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='touched_accounts', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='return_data', + value=Constant(value=b'')), + keyword( + arg='error', + value=Constant(value=None)), + keyword( + arg='accessed_addresses', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='accessed_addresses', + ctx=Load())), + keyword( + arg='accessed_storage_keys', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))]), + ExceptHandler( + type=Name(id='Revert', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/interpreter.v b/coq/ethereum/arrow_glacier/vm/interpreter.v new file mode 100644 index 0000000000..760d983860 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/interpreter.v @@ -0,0 +1,173 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.arrow_glacier.blocks. +Require ethereum.arrow_glacier.fork_types. +Require ethereum.arrow_glacier.state. +Require ethereum.arrow_glacier.vm. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.precompiled_contracts.mapping. +Require ethereum.arrow_glacier.vm.__init__. +Require ethereum.arrow_glacier.vm.exceptions. +Require ethereum.arrow_glacier.vm.instructions. +Require ethereum.arrow_glacier.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.mark_account_created ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/memory.ast b/coq/ethereum/arrow_glacier/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/memory.v b/coq/ethereum/arrow_glacier/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..bb9991907f --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS'), + Constant(value='MODEXP_ADDRESS'), + Constant(value='ALT_BN128_ADD_ADDRESS'), + Constant(value='ALT_BN128_MUL_ADDRESS'), + Constant(value='ALT_BN128_PAIRING_CHECK_ADDRESS'), + Constant(value='BLAKE2F_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[])), + Assign( + targets=[ + Name(id='MODEXP_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x05')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x06')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x07')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x08')], + keywords=[])), + Assign( + targets=[ + Name(id='BLAKE2F_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x09')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..ca8d08f70e --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.arrow_glacier.utils.hexadecimal. diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.ast new file mode 100644 index 0000000000..f6f077419c --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.ast @@ -0,0 +1,913 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ALT_BN128 CONTRACTS\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ALT_BN128 precompiled contracts.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.alt_bn128', + names=[ + alias(name='ALT_BN128_CURVE_ORDER'), + alias(name='ALT_BN128_PRIME'), + alias(name='BNF'), + alias(name='BNF2'), + alias(name='BNF12'), + alias(name='BNP'), + alias(name='BNP2'), + alias(name='pairing')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=2), + FunctionDef( + name='alt_bn128_add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 addition precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=150)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load()), + Name(id='x1_value', ctx=Load()), + Name(id='y1_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='p1', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x1_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y1_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=BinOp( + left=Name(id='p0', ctx=Load()), + op=Add(), + right=Name(id='p1', ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 multiplication precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6000)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='n', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='p0', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='n', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_pairing_check', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 pairing check precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=34000), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))), + op=Add(), + right=Constant(value=45000))], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=192)), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='values', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=Name(id='j', ctx=Load()))), + upper=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=BinOp( + left=Name(id='j', ctx=Load()), + op=Add(), + right=Constant(value=1))))), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='values', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=Call( + func=Name(id='BNP2', ctx=Load()), + args=[ + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=3), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=2), + ctx=Load())], + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=5), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=4), + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='OutOfGasError', ctx=Load()), + args=[], + keywords=[]))])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='p', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='q', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='p', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + Compare( + left=Name(id='q', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='result', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='pairing', ctx=Load()), + args=[ + Name(id='q', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[])))], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='result', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000000..b5ef656727 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,226 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.alt_bn128. +Require ethereum.arrow_glacier.vm. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.memory. +Require ethereum.arrow_glacier.vm.exceptions. + +Definition alt_bn128_add (evm : Evm) : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 150 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "x1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x1_bytes" |) + |) + |) in + ]] in + do* M.assign "y1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y1_bytes" |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + (* TODO expression *) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_mul (evm : Evm) : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 6000 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "n" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + M.get_field ~(| M.get_local ~(| "p0" |), "mul_by" |) ~(| + M.get_local ~(| "n" |) + |) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_pairing_check (evm : Evm) : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + (* TODO expression *) + |) + |) ]] in + (* TODO statement *) + do* M.assign "result" [[ + M.get_field ~(| ethereum.crypto.alt_bn128.BNF12, "from_int" |) ~(| + 1 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.ast new file mode 100644 index 0000000000..03747962f0 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.ast @@ -0,0 +1,137 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `Blake2` precompiled contract.\n')), + ImportFrom( + module='ethereum.crypto.blake2', + names=[ + alias(name='Blake2b')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BLAKE2_PER_ROUND'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidParameter')], + level=2), + FunctionDef( + name='blake2f', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the Blake2 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Constant(value=213)]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='blake2b', ctx=Store())], + value=Call( + func=Name(id='Blake2b', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='rounds', ctx=Store()), + Name(id='h', ctx=Store()), + Name(id='m', ctx=Store()), + Name(id='t_0', ctx=Store()), + Name(id='t_1', ctx=Store()), + Name(id='f', ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='get_blake2_parameters', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_BLAKE2_PER_ROUND', ctx=Load()), + op=Mult(), + right=Name(id='rounds', ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=Name(id='f', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + List( + elts=[ + Constant(value=0), + Constant(value=1)], + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='compress', + ctx=Load()), + args=[ + Name(id='rounds', ctx=Load()), + Name(id='h', ctx=Load()), + Name(id='m', ctx=Load()), + Name(id='t_0', ctx=Load()), + Name(id='t_1', ctx=Load()), + Name(id='f', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000000..2ae5a638c5 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,46 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +*) + +Require ethereum.crypto.blake2. +Require ethereum.arrow_glacier.vm. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.exceptions. + +Definition blake2f (evm : Evm) : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + (* TODO statement *) + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| + + |) in + ]] in + (* TODO assignment *) + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..b888925e4e --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.arrow_glacier.vm. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/identity.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/identity.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..f36654cccc --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.arrow_glacier.vm. +Require ethereum.arrow_glacier.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..cec40e5736 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ALT_BN128_ADD_ADDRESS'), + alias(name='ALT_BN128_MUL_ADDRESS'), + alias(name='ALT_BN128_PAIRING_CHECK_ADDRESS'), + alias(name='BLAKE2F_ADDRESS'), + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='MODEXP_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='alt_bn128', + names=[ + alias(name='alt_bn128_add'), + alias(name='alt_bn128_mul'), + alias(name='alt_bn128_pairing_check')], + level=1), + ImportFrom( + module='blake2f', + names=[ + alias(name='blake2f')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='modexp', + names=[ + alias(name='modexp')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load()), + Name(id='MODEXP_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Load()), + Name(id='BLAKE2F_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load()), + Name(id='modexp', ctx=Load()), + Name(id='alt_bn128_add', ctx=Load()), + Name(id='alt_bn128_mul', ctx=Load()), + Name(id='alt_bn128_pairing_check', ctx=Load()), + Name(id='blake2f', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..3d3ba315ea --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/mapping.v @@ -0,0 +1,25 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.arrow_glacier.fork_types. +Require ethereum.arrow_glacier.vm.precompiled_contracts.__init__. +Require ethereum.arrow_glacier.vm.precompiled_contracts.alt_bn128. +Require ethereum.arrow_glacier.vm.precompiled_contracts.blake2f. +Require ethereum.arrow_glacier.vm.precompiled_contracts.ecrecover. +Require ethereum.arrow_glacier.vm.precompiled_contracts.identity. +Require ethereum.arrow_glacier.vm.precompiled_contracts.modexp. +Require ethereum.arrow_glacier.vm.precompiled_contracts.ripemd160. +Require ethereum.arrow_glacier.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.ast new file mode 100644 index 0000000000..42ecfa223f --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.ast @@ -0,0 +1,638 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `MODEXP` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + Assign( + targets=[ + Name(id='GQUADDIVISOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + FunctionDef( + name='modexp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and.\n `modulus`. The return value is the same length as the modulus.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='base_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_start', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Add(), + right=Name(id='base_length', ctx=Load()))), + Assign( + targets=[ + Name(id='exp_head', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Call( + func=Name(id='min', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='gas_cost', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load()), + Name(id='exp_length', ctx=Load()), + Name(id='exp_head', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='base_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='modulus_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Name(id='base_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_start', ctx=Store())], + value=BinOp( + left=Name(id='exp_start', ctx=Load()), + op=Add(), + right=Name(id='exp_length', ctx=Load()))), + Assign( + targets=[ + Name(id='modulus', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='modulus_start', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='modulus', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'\x00')], + keywords=[]), + op=Mult(), + right=Name(id='modulus_length', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exp', ctx=Load()), + Name(id='modulus', ctx=Load())], + keywords=[]), + attr='to_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[]), + Constant(value='big')], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='complexity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Estimate the complexity of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n Returns\n -------\n\n complexity : `Uint`\n Complexity of performing the operation.\n ')), + Assign( + targets=[ + Name(id='max_length', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load())], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Return( + value=BinOp( + left=Name(id='words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='iterations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the number of iterations required to perform a modular\n exponentiation.\n\n Parameters\n ----------\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n iterations : `Uint`\n Number of iterations.\n ')), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + Compare( + left=Name(id='exponent_head', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='bit_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='bit_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='bit_length', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Name(id='bit_length', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='length_part', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])))), + Assign( + targets=[ + Name(id='bits_part', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='bits_part', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='bits_part', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=BinOp( + left=Name(id='length_part', ctx=Load()), + op=Add(), + right=Name(id='bits_part', ctx=Load())))])]), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='count', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the gas cost of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n gas_cost : `Uint`\n Gas required for performing the operation.\n ')), + Assign( + targets=[ + Name(id='multiplication_complexity', ctx=Store())], + value=Call( + func=Name(id='complexity', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='iteration_count', ctx=Store())], + value=Call( + func=Name(id='iterations', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load()), + Name(id='exponent_head', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cost', ctx=Store())], + value=BinOp( + left=Name(id='multiplication_complexity', ctx=Load()), + op=Mult(), + right=Name(id='iteration_count', ctx=Load()))), + AugAssign( + target=Name(id='cost', ctx=Store()), + op=FloorDiv(), + value=Name(id='GQUADDIVISOR', ctx=Load())), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[]), + Name(id='cost', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000000..18b26d0ed0 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/modexp.v @@ -0,0 +1,236 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.arrow_glacier.vm. +Require ethereum.arrow_glacier.vm.gas. +Require ethereum.arrow_glacier.vm.memory. + +Definition modexp (evm : Evm) : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "base_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "modulus_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "exp_head" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "min" |) ~(| + ethereum_types.numeric.U256 ~(| + 32 + |), + M.get_local ~(| "exp_length" |) + |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) ~(| + M.get_local ~(| "base_length" |), + M.get_local ~(| "modulus_length" |), + M.get_local ~(| "exp_length" |), + M.get_local ~(| "exp_head" |) + |) + |) ]] in + (* TODO statement *) + do* M.assign "base" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + M.get_local ~(| "base_length" |) + |) + |) in + ]] in + do* M.assign "exp" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "exp_length" |) + |) + |) in + ]] in + do* M.assign "modulus_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "modulus" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "modulus_start" |), + M.get_local ~(| "modulus_length" |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := + (* + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + *) + do* M.assign "max_length" [[ + M.get_local ~(| "max" |) ~(| + ethereum_types.numeric.Uint ~(| + base_length + |), + ethereum_types.numeric.Uint ~(| + modulus_length + |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition gas_cost (base_length : U256) (modulus_length : U256) (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + *) + do* M.assign "multiplication_complexity" [[ + M.get_local ~(| "complexity" |) ~(| + base_length, + modulus_length + |) in + ]] in + do* M.assign "iteration_count" [[ + M.get_local ~(| "iterations" |) ~(| + exponent_length, + exponent_head + |) in + ]] in + do* M.assign "cost" [[ + (* TODO expression *) in + ]] in + do* M.aug_assign [[ M.get_local ~(| "cost" |) ]] [[ + M.get_local ~(| "GQUADDIVISOR" |) + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.ast b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.v b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/runtime.ast b/coq/ethereum/arrow_glacier/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/runtime.v b/coq/ethereum/arrow_glacier/vm/runtime.v new file mode 100644 index 0000000000..3644a412c3 --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.arrow_glacier.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/arrow_glacier/vm/stack.ast b/coq/ethereum/arrow_glacier/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/arrow_glacier/vm/stack.v b/coq/ethereum/arrow_glacier/vm/stack.v new file mode 100644 index 0000000000..a1b907222b --- /dev/null +++ b/coq/ethereum/arrow_glacier/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.arrow_glacier.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/__init__.ast b/coq/ethereum/berlin/__init__.ast new file mode 100644 index 0000000000..1bf73b4ab3 --- /dev/null +++ b/coq/ethereum/berlin/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe Berlin fork adjusts the gas costs of the `ModExp` precompile and several\nstate access EVM instructions, introduces typed transaction envelopes along\nwith the first new transaction type—optional access lists.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=12244000)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/__init__.v b/coq/ethereum/berlin/__init__.v new file mode 100644 index 0000000000..3ae2342594 --- /dev/null +++ b/coq/ethereum/berlin/__init__.v @@ -0,0 +1,8 @@ +(* Generated *) +(* +The Berlin fork adjusts the gas costs of the `ModExp` precompile and several +state access EVM instructions, introduces typed transaction envelopes along +with the first new transaction type—optional access lists. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/berlin/blocks.ast b/coq/ethereum/berlin/blocks.ast new file mode 100644 index 0000000000..ea890a59fb --- /dev/null +++ b/coq/ethereum/berlin/blocks.ast @@ -0,0 +1,226 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='LegacyTransaction')], + level=1), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mix_digest', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='succeeded', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/blocks.v b/coq/ethereum/berlin/blocks.v new file mode 100644 index 0000000000..69c606999d --- /dev/null +++ b/coq/ethereum/berlin/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.berlin.fork_types. +Require ethereum.berlin.transactions. diff --git a/coq/ethereum/berlin/bloom.ast b/coq/ethereum/berlin/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/berlin/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/bloom.v b/coq/ethereum/berlin/bloom.v new file mode 100644 index 0000000000..d3ecba981b --- /dev/null +++ b/coq/ethereum/berlin/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.berlin.blocks. +Require ethereum.berlin.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/exceptions.ast b/coq/ethereum/berlin/exceptions.ast new file mode 100644 index 0000000000..a61ee25448 --- /dev/null +++ b/coq/ethereum/berlin/exceptions.ast @@ -0,0 +1,72 @@ +Module( + body=[ + Expr( + value=Constant(value='\nExceptions specific to this fork.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Final')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidTransaction')], + level=0), + ClassDef( + name='TransactionTypeError', + bases=[ + Name(id='InvalidTransaction', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Unknown [EIP-2718] transaction type byte.\n\n [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718\n ')), + AnnAssign( + target=Name(id='transaction_type', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n The type byte of the transaction that caused the error.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='transaction_type', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='unknown transaction type `'), + FormattedValue( + value=Name(id='transaction_type', ctx=Load()), + conversion=-1), + Constant(value='`')])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='transaction_type', + ctx=Store())], + value=Name(id='transaction_type', ctx=Load()))], + decorator_list=[])], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/exceptions.v b/coq/ethereum/berlin/exceptions.v new file mode 100644 index 0000000000..9a313f6d0e --- /dev/null +++ b/coq/ethereum/berlin/exceptions.v @@ -0,0 +1,7 @@ +(* Generated *) +(* +Exceptions specific to this fork. +*) + +Require typing. +Require ethereum.exceptions. diff --git a/coq/ethereum/berlin/fork.ast b/coq/ethereum/berlin/fork.ast new file mode 100644 index 0000000000..d6e1913f0e --- /dev/null +++ b/coq/ethereum/berlin/fork.ast @@ -0,0 +1,3477 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.ethash', + names=[ + alias(name='dataset_size'), + alias(name='generate_cache'), + alias(name='hashimoto_light')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty'), + alias(name='create_ether'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_ACCESS_LIST_ADDRESS_COST'), + alias(name='TX_ACCESS_LIST_STORAGE_KEY_COST'), + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='AccessListTransaction'), + alias(name='LegacyTransaction'), + alias(name='Transaction'), + alias(name='decode_transaction'), + alias(name='encode_transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BLOCK_REWARD', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=18)))], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=131072)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_OMMER_DEPTH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='BOMB_DELAY_BLOCKS', ctx=Store())], + value=Constant(value=9000000)), + Assign( + targets=[ + Name(id='EMPTY_OMMER_HASH', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List(elts=[], ctx=Load())], + keywords=[])], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='validate_ommers', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='chain', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='chain', ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + Assign( + targets=[ + Name(id='parent_has_ommers', ctx=Store())], + value=Compare( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='EMPTY_OMMER_HASH', ctx=Load())])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_difficulty', ctx=Store())], + value=Call( + func=Name(id='calculate_block_difficulty', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Name(id='parent_has_ommers', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_difficulty', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='validate_proof_of_work', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generate_header_hash_for_pow', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate rlp hash of the header which is to be used for Proof-of-Work\n verification.\n\n In other words, the PoW artefacts `mix_digest` and `nonce` are ignored\n while calculating this hash.\n\n A particular PoW is valid for a single hash, that hash is computed by\n this function. The `nonce` and `mix_digest` are omitted from this hash\n because they are being changed by miners in their search for a sufficient\n proof-of-work.\n\n Parameters\n ----------\n header :\n The header object for which the hash is to be generated.\n\n Returns\n -------\n hash : `Hash32`\n The PoW valid rlp hash of the passed in header.\n ')), + Assign( + targets=[ + Name(id='header_data_without_pow_artefacts', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='state_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='transactions_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='receipt_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='bloom', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='header_data_without_pow_artefacts', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='validate_proof_of_work', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the Proof of Work constraints.\n\n In order to verify that a miner's proof-of-work is valid for a block, a\n ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``\n hash function. The mix digest is a hash of the header and the nonce that\n is passed through and it confirms whether or not proof-of-work was done\n on the correct block. The result is the actual hash value of the block.\n\n Parameters\n ----------\n header :\n Header of interest.\n ")), + Assign( + targets=[ + Name(id='header_hash', ctx=Store())], + value=Call( + func=Name(id='generate_header_hash_for_pow', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache', ctx=Store())], + value=Call( + func=Name(id='generate_cache', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='mix_digest', ctx=Store()), + Name(id='result', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='hashimoto_light', ctx=Load()), + args=[ + Name(id='header_hash', ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + Name(id='cache', ctx=Load()), + Call( + func=Name(id='dataset_size', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='mix_digest', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='mix_digest', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='limit', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='limit', ctx=Load()), + op=FloorDiv(), + right=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n gas_available :\n The gas remaining in the block.\n chain_id :\n The ID of the current chain.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + Return( + value=Name(id='sender_address', ctx=Load()))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='error', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n error :\n Error in the top level frame of the transaction, if any.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='succeeded', + value=Compare( + left=Name(id='error', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)])), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='receipt', ctx=Load())], + keywords=[])))], + orelse=[ + Return( + value=Name(id='receipt', ctx=Load()))])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Receipt', ctx=Load())], + ctx=Load()), + ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='block_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n block_difficulty :\n Difficulty of the block.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Receipt', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Call( + func=Name(id='map', ctx=Load()), + args=[ + Name(id='decode_transaction', ctx=Load()), + Name(id='transactions', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Call( + func=Name(id='encode_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='gas_available', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='gas_price', + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='difficulty', + value=Name(id='block_difficulty', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='chain_id', + value=Name(id='chain_id', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store()), + Name(id='error', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='error', ctx=Load()), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='pay_rewards', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='block_number', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='ommers', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='validate_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='block_header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the ommers mentioned in the block.\n\n An ommer block is a block that wasn't canonically added to the\n blockchain because it wasn't validated as fast as the canonical block\n but was mined at the same time.\n\n To be considered valid, the ommers must adhere to the rules defined in\n the Ethereum protocol. The maximum amount of ommers is 2 per block and\n there cannot be duplicate ommers in a block. Many of the other ommer\n constraints are listed in the in-line comments of this function.\n\n Parameters\n ----------\n ommers :\n List of ommers mentioned in the current block.\n block_header:\n The header of current block.\n chain :\n History and current state.\n ")), + Assign( + targets=[ + Name(id='block_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='block_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='ommers_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return()], + orelse=[]), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + op=Sub(), + right=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Name(id='ommer', ctx=Load()), + Name(id='ommer_parent_header', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=2)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommers_hashes', ctx=Store())], + value=ListComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + ifs=[], + is_async=0)])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[])], + keywords=[])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_canonical_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=BinOp( + left=Name(id='MAX_OMMER_DEPTH', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + ctx=Load())), + Assign( + targets=[ + Name(id='recent_canonical_block_hashes', ctx=Store())], + value=SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='recent_ommers_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + simple=1), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='recent_ommers_hashes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='recent_ommers_hashes', ctx=Load()), + attr='union', + ctx=Load()), + args=[ + SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='ommer_index', ctx=Store()), + Name(id='ommer', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='ommer_hash', ctx=Store())], + value=Subscript( + value=Name(id='ommers_hashes', ctx=Load()), + slice=Name(id='ommer_index', ctx=Load()), + ctx=Load())), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='block_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_ommers_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='ommer_age', ctx=Load())]), + Compare( + left=Name(id='ommer_age', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_OMMER_DEPTH', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='parent_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pay_rewards', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pay rewards to the block miner as well as the ommers miners.\n\n The miner of the canonical block is rewarded with the predetermined\n block reward, ``BLOCK_REWARD``, plus a variable award based off of the\n number of ommer blocks that were mined around the same time, and included\n in the canonical block's header. An ommer block is a block that wasn't\n added to the canonical blockchain because it wasn't validated as fast as\n the accepted block but was mined at the same time. Although not all blocks\n that are mined are added to the canonical chain, miners are still paid a\n reward for their efforts. This reward is called an ommer reward and is\n calculated based on the number associated with the ommer block that they\n mined.\n\n Parameters\n ----------\n state :\n Current account state.\n block_number :\n Position of the block within the chain.\n coinbase :\n Address of account which receives block reward and transaction fees.\n ommers :\n List of ommers mentioned in the current block.\n ")), + Assign( + targets=[ + Name(id='ommer_count', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='miner_reward', ctx=Store())], + value=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='ommer_count', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='miner_reward', ctx=Load())], + keywords=[])), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_number', ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='ommer_miner_reward', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Sub(), + right=Name(id='ommer_age', ctx=Load())), + op=Mult(), + right=Name(id='BLOCK_REWARD', ctx=Load())), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='ommer_miner_reward', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='preaccessed_addresses', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='preaccessed_storage_keys', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='address', ctx=Store()), + Name(id='keys', ctx=Store())], + ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='keys', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_storage_keys', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Name(id='address', ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[ + keyword( + arg='preaccessed_addresses', + value=Call( + func=Name(id='frozenset', ctx=Load()), + args=[ + Name(id='preaccessed_addresses', ctx=Load())], + keywords=[])), + keyword( + arg='preaccessed_storage_keys', + value=Call( + func=Name(id='frozenset', ctx=Load()), + args=[ + Name(id='preaccessed_storage_keys', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + If( + test=Compare( + left=Name(id='coinbase_balance_after_mining_fee', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]))], + orelse=[])]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='error', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Name(id='TX_CREATE_COST', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Assign( + targets=[ + Name(id='access_list_cost', ctx=Store())], + value=Constant(value=0)), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='_address', ctx=Store()), + Name(id='keys', ctx=Store())], + ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + body=[ + AugAssign( + target=Name(id='access_list_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_ACCESS_LIST_ADDRESS_COST', ctx=Load())), + AugAssign( + target=Name(id='access_list_cost', ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='keys', ctx=Load())], + keywords=[]), + op=Mult(), + right=Name(id='TX_ACCESS_LIST_STORAGE_KEY_COST', ctx=Load())))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load())), + op=Add(), + right=Name(id='access_list_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=28)])]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash_pre155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='chain_id_x2', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=36)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[])), + op=Sub(), + right=Name(id='chain_id_x2', ctx=Load())), + Call( + func=Name(id='signing_hash_155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])], + keywords=[]))])], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='y_parity', + ctx=Load()), + Call( + func=Name(id='signing_hash_2930', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash_pre155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a legacy (pre EIP 155) signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 155 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n The id of the current chain.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='chain_id', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_2930', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='AccessListTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 2930 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load())], + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_has_ommers', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes difficulty of a block using its header and parent header.\n\n The difficulty is determined by the time the block was created after its\n parent. The ``offset`` is calculated using the parent block's difficulty,\n ``parent_difficulty``, and the timestamp between blocks. This offset is\n then added to the parent difficulty and is stored as the ``difficulty``\n variable. If the time between the block and its parent is too short, the\n offset will result in a positive number thus making the sum of\n ``parent_difficulty`` and ``offset`` to be a greater value in order to\n avoid mass forking. But, if the time is long enough, then the offset\n results in a negative value making the block less difficult than\n its parent.\n\n The base standard for a block's difficulty is the predefined value\n set for the genesis block since it has no parent. So, a block\n can't be less difficult than the genesis block, therefore each block's\n difficulty is set to the maximum value between the calculated\n difficulty and the ``GENESIS_DIFFICULTY``.\n\n Parameters\n ----------\n block_number :\n Block number of the block.\n block_timestamp :\n Timestamp of the block.\n parent_timestamp :\n Timestamp of the parent block.\n parent_difficulty :\n difficulty of the parent block.\n parent_has_ommers:\n does the parent have ommers.\n\n Returns\n -------\n difficulty : `ethereum.base_types.Uint`\n Computed difficulty for a block.\n ")), + Assign( + targets=[ + Name(id='offset', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=2048)), + op=Mult(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=IfExp( + test=Name(id='parent_has_ommers', ctx=Load()), + body=Constant(value=2), + orelse=Constant(value=1)), + op=Sub(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_timestamp', ctx=Load()), + op=Sub(), + right=Name(id='parent_timestamp', ctx=Load()))], + keywords=[]), + op=FloorDiv(), + right=Constant(value=9))), + UnaryOp( + op=USub(), + operand=Constant(value=99))], + keywords=[]))), + Assign( + targets=[ + Name(id='difficulty', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='offset', ctx=Load()))), + Assign( + targets=[ + Name(id='num_bomb_periods', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='BOMB_DELAY_BLOCKS', ctx=Load())), + op=FloorDiv(), + right=Constant(value=100000)), + op=Sub(), + right=Constant(value=2))), + If( + test=Compare( + left=Name(id='num_bomb_periods', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='difficulty', ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Name(id='num_bomb_periods', ctx=Load())))], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='difficulty', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/fork.v b/coq/ethereum/berlin/fork.v new file mode 100644 index 0000000000..f2e5ffdc2a --- /dev/null +++ b/coq/ethereum/berlin/fork.v @@ -0,0 +1,879 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.ethash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.berlin.__init__. +Require ethereum.berlin.blocks. +Require ethereum.berlin.bloom. +Require ethereum.berlin.fork_types. +Require ethereum.berlin.state. +Require ethereum.berlin.transactions. +Require ethereum.berlin.trie. +Require ethereum.berlin.utils.message. +Require ethereum.berlin.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + do* [[ M.get_local ~(| "validate_ommers" |) ~(| + M.get_field ~(| block, "ommers" |), + M.get_field ~(| block, "header" |), + chain + |) ]] in + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "difficulty" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| block, "ommers" |), + M.get_field ~(| chain, "chain_id" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + do* M.assign "parent_has_ommers" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_difficulty" [[ + M.get_local ~(| "calculate_block_difficulty" |) ~(| + M.get_field ~(| header, "number" |), + M.get_field ~(| header, "timestamp" |), + M.get_field ~(| parent_header, "timestamp" |), + M.get_field ~(| parent_header, "difficulty" |), + M.get_local ~(| "parent_has_ommers" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| + header + |) ]] in + M.pure tt. + +Definition generate_header_hash_for_pow (header : Header) : M Hash32 := + (* + 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. + *) + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_proof_of_work (header : Header) : M unit := + (* + 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. + *) + do* M.assign "header_hash" [[ + M.get_local ~(| "generate_header_hash_for_pow" |) ~(| + header + |) in + ]] in + do* M.assign "cache" [[ + ethereum.ethash.generate_cache ~(| + M.get_field ~(| header, "number" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (gas_available : Uint) (chain_id : U64) : M Address := + (* + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (error : (* TODO type *)) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (block_gas_limit : Uint) (block_time : U256) (block_difficulty : Uint) (transactions : (* TODO type *)) (ommers : (* TODO type *)) (chain_id : U64) : M ApplyBodyOutput := + (* + 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.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "pay_rewards" |) ~(| + state, + block_number, + coinbase, + ommers + |) ]] in + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_ommers (ommers : (* TODO type *)) (block_header : Header) (chain : BlockChain) : M unit := + (* + 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. + *) + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_canonical_blocks" [[ + (* TODO expression *) in + ]] in + do* M.assign "recent_canonical_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition pay_rewards (state : State) (block_number : Uint) (coinbase : Address) (ommers : (* TODO type *)) : M unit := + (* + 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. + *) + do* M.assign "ommer_count" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + ommers + |) + |) in + ]] in + do* M.assign "miner_reward" [[ + (* TODO expression *) in + ]] in + do* [[ state.create_ether ~(| + state, + coinbase, + M.get_local ~(| "miner_reward" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + do* M.assign "gas_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "preaccessed_addresses" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "preaccessed_storage_keys" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + (* TODO statement *) + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "access_list_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_pre155 (tx : Transaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_155 (tx : Transaction) (chain_id : U64) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_2930 (tx : AccessListTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_block_difficulty (block_number : Uint) (block_timestamp : U256) (parent_timestamp : U256) (parent_difficulty : Uint) (parent_has_ommers : bool) : M Uint := + (* + 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. + *) + do* M.assign "offset" [[ + (* TODO expression *) in + ]] in + do* M.assign "difficulty" [[ + (* TODO expression *) in + ]] in + do* M.assign "num_bomb_periods" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/fork_types.ast b/coq/ethereum/berlin/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/berlin/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/fork_types.v b/coq/ethereum/berlin/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/berlin/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/state.ast b/coq/ethereum/berlin/state.ast new file mode 100644 index 0000000000..c04909fdce --- /dev/null +++ b/coq/ethereum/berlin/state.ast @@ -0,0 +1,1692 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='created_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='set', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mark_account_created', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Mark an account as having been created in the current transaction.\n This information is used by `get_storage_original()` to handle an obscure\n edgecase.\n\n The marker is not removed even if the account creation reverts. Since the\n account cannot have had code prior to its creation and can't call\n `get_storage_original()`, this is harmless.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account that has been created.\n ")), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has zero nonce, empty code and zero balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_empty : `bool`\n True if if an account has zero nonce, empty code and zero balance,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_exists_and_is_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists and has zero nonce, empty code and zero\n balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n exists_and_is_empty : `bool`\n True if an account exists and has zero nonce, empty code and zero\n balance, False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='account', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_alive', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether is an account is both in the state and non empty.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_alive : `bool`\n True if the account is alive.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[ + Return( + value=UnaryOp( + op=Not(), + operand=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])])))])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add newly created ether to an account.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to which ether is added.\n amount:\n The amount of ether to be added to the account of interest.\n ')), + FunctionDef( + name='increase_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage_original', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the original value in a storage slot i.e. the value before the current\n transaction began. This function reads the value from the snapshots taken\n before executing the transaction.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to read the value from.\n key:\n Key of the storage slot.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='_', ctx=Store()), + Name(id='original_trie', ctx=Store())], + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + Assign( + targets=[ + Name(id='original_account_trie', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='original_trie', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='original_account_trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='original_account_trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[]))]), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='original_value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='original_value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/state.v b/coq/ethereum/berlin/state.v new file mode 100644 index 0000000000..c6e132c46f --- /dev/null +++ b/coq/ethereum/berlin/state.v @@ -0,0 +1,614 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.berlin.fork_types. +Require ethereum.berlin.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition mark_account_created (state : State) (address : Address) : M unit := + (* + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| + address + |) ]] in + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_empty (state : State) (address : Address) : M bool := + (* + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition account_exists_and_is_empty (state : State) (address : Address) : M bool := + (* + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_alive (state : State) (address : Address) : M bool := + (* + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := + (* + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. + +Definition get_storage_original (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + *) + (* TODO statement *) + (* TODO assignment *) + do* M.assign "original_account_trie" [[ + M.get_field ~(| M.get_local ~(| "original_trie" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/transactions.ast b/coq/ethereum/berlin/transactions.ast new file mode 100644 index 0000000000..d11e21693f --- /dev/null +++ b/coq/ethereum/berlin/transactions.ast @@ -0,0 +1,358 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='TransactionTypeError')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + Assign( + targets=[ + Name(id='TX_ACCESS_LIST_ADDRESS_COST', ctx=Store())], + value=Constant(value=2400)), + Assign( + targets=[ + Name(id='TX_ACCESS_LIST_STORAGE_KEY_COST', ctx=Store())], + value=Constant(value=1900)), + ClassDef( + name='LegacyTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='AccessListTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The transaction type added in EIP-2930 to support access lists.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='access_list', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y_parity', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='Transaction', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Encode a transaction. Needed because non-legacy transactions aren't RLP.\n ")), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='tx', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])))], + orelse=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Unable to encode transaction of type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + conversion=-1)])], + keywords=[]))])])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='decode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Decode a transaction. Needed because non-legacy transactions aren't RLP.\n ")), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=1)]), + body=[ + Raise( + exc=Call( + func=Name(id='TransactionTypeError', ctx=Load()), + args=[ + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Name(id='AccessListTransaction', ctx=Load()), + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='tx', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Transaction', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/transactions.v b/coq/ethereum/berlin/transactions.v new file mode 100644 index 0000000000..2e04a2a104 --- /dev/null +++ b/coq/ethereum/berlin/transactions.v @@ -0,0 +1,29 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.berlin.exceptions. +Require ethereum.berlin.fork_types. + +Definition encode_transaction (tx : Transaction) : M (* TODO type *) := + (* + Encode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + M.pure tt. + +Definition decode_transaction (tx : (* TODO type *)) : M Transaction := + (* + Decode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/trie.ast b/coq/ethereum/berlin/trie.ast new file mode 100644 index 0000000000..5499197517 --- /dev/null +++ b/coq/ethereum/berlin/trie.ast @@ -0,0 +1,1632 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.muir_glacier', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='LegacyTransaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Receipt', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.RLP`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `eth1spec.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `eth1spec.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/trie.v b/coq/ethereum/berlin/trie.v new file mode 100644 index 0000000000..2e36b195fc --- /dev/null +++ b/coq/ethereum/berlin/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `eth1spec.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `eth1spec.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/utils/__init__.ast b/coq/ethereum/berlin/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/berlin/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/utils/__init__.v b/coq/ethereum/berlin/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/berlin/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/berlin/utils/address.ast b/coq/ethereum/berlin/utils/address.ast new file mode 100644 index 0000000000..d7432ad506 --- /dev/null +++ b/coq/ethereum/berlin/utils/address.ast @@ -0,0 +1,216 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this berlin version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_create2_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='salt', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='call_data', + annotation=Name(id='bytearray', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created, which is\n based on the sender address, salt and the call data as well.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n salt :\n Address generation salt.\n call_data :\n The code of the new account which is to be created.\n\n Returns\n -------\n address: `ethereum.berlin.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='preimage', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Constant(value=b'\xff'), + op=Add(), + right=Name(id='address', ctx=Load())), + op=Add(), + right=Name(id='salt', ctx=Load())), + op=Add(), + right=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='call_data', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/utils/address.v b/coq/ethereum/berlin/utils/address.v new file mode 100644 index 0000000000..81def78a3d --- /dev/null +++ b/coq/ethereum/berlin/utils/address.v @@ -0,0 +1,115 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this berlin version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.berlin.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition compute_create2_contract_address (address : Address) (salt : Bytes32) (call_data : bytearray) : M Address := + (* + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.berlin.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "preimage" [[ + (* TODO expression *) in + ]] in + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "preimage" |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/utils/hexadecimal.ast b/coq/ethereum/berlin/utils/hexadecimal.ast new file mode 100644 index 0000000000..c6bda0c465 --- /dev/null +++ b/coq/ethereum/berlin/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to\nBerlin types.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/utils/hexadecimal.v b/coq/ethereum/berlin/utils/hexadecimal.v new file mode 100644 index 0000000000..805db3fa5a --- /dev/null +++ b/coq/ethereum/berlin/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Berlin types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.berlin.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/utils/message.ast b/coq/ethereum/berlin/utils/message.ast new file mode 100644 index 0000000000..a89c7fe469 --- /dev/null +++ b/coq/ethereum/berlin/utils/message.ast @@ -0,0 +1,335 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this berlin version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='FrozenSet'), + alias(name='Optional'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_static', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='preaccessed_addresses', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='preaccessed_storage_keys', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True), + Constant(value=False), + Call( + func=Name(id='frozenset', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='frozenset', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n is_static:\n if True then it prevents all state-changing operations from being\n executed.\n preaccessed_addresses:\n Addresses that should be marked as accessed prior to the message call\n preaccessed_storage_keys:\n Storage keys that should be marked as accessed prior to the message\n call\n\n Returns\n -------\n message: `ethereum.berlin.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Assign( + targets=[ + Name(id='accessed_addresses', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='current_target', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='caller', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Name(id='preaccessed_addresses', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=Name(id='is_static', ctx=Load())), + keyword( + arg='accessed_addresses', + value=Name(id='accessed_addresses', ctx=Load())), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='preaccessed_storage_keys', ctx=Load())], + keywords=[])), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/utils/message.v b/coq/ethereum/berlin/utils/message.v new file mode 100644 index 0000000000..afbdb95cc4 --- /dev/null +++ b/coq/ethereum/berlin/utils/message.v @@ -0,0 +1,85 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this berlin version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.berlin.fork_types. +Require ethereum.berlin.state. +Require ethereum.berlin.vm. +Require ethereum.berlin.vm.precompiled_contracts.mapping. +Require ethereum.berlin.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) (is_static : bool) (preaccessed_addresses : (* TODO type *)) (preaccessed_storage_keys : (* TODO type *)) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.berlin.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + do* M.assign "accessed_addresses" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "add" |) ~(| + M.get_local ~(| "current_target" |) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "add" |) ~(| + caller + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS, "keys" |) ~(| + + |) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + preaccessed_addresses + |) ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/vm/__init__.ast b/coq/ethereum/berlin/vm/__init__.ast new file mode 100644 index 0000000000..6850aa3e02 --- /dev/null +++ b/coq/ethereum/berlin/vm/__init__.ast @@ -0,0 +1,587 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty')], + level=2), + ImportFrom( + module='precompiled_contracts', + names=[ + alias(name='RIPEMD160_ADDRESS')], + level=1), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='is_static', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_addresses', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_storage_keys', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='return_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_addresses', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_storage_keys', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + If( + test=Compare( + left=Name(id='RIPEMD160_ADDRESS', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/__init__.v b/coq/ethereum/berlin/vm/__init__.v new file mode 100644 index 0000000000..8168b47b26 --- /dev/null +++ b/coq/ethereum/berlin/vm/__init__.v @@ -0,0 +1,78 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.berlin.blocks. +Require ethereum.berlin.fork_types. +Require ethereum.berlin.state. +Require ethereum.berlin.vm.precompiled_contracts. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "touched_accounts" |), "update" |) ~(| + M.get_field ~(| child_evm, "touched_accounts" |) + |) ]] in + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| child_evm, "accessed_addresses" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_storage_keys" |), "update" |) ~(| + M.get_field ~(| child_evm, "accessed_storage_keys" |) + |) ]] in + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + (* TODO statement *) + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/berlin/vm/exceptions.ast b/coq/ethereum/berlin/vm/exceptions.ast new file mode 100644 index 0000000000..1a05416bbd --- /dev/null +++ b/coq/ethereum/berlin/vm/exceptions.ast @@ -0,0 +1,165 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='Revert', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised by the `REVERT` opcode.\n\n Unlike other EVM exceptions this does not result in the consumption of all\n gas.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='WriteInStaticContext', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt is made to modify the state while operating inside\n of a STATICCALL context.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfBoundsRead', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt was made to read data beyond the\n boundaries of the buffer.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidParameter', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when invalid parameters are passed.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/exceptions.v b/coq/ethereum/berlin/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/berlin/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/berlin/vm/gas.ast b/coq/ethereum/berlin/vm/gas.ast new file mode 100644 index 0000000000..d095bb7303 --- /dev/null +++ b/coq/ethereum/berlin/vm/gas.ast @@ -0,0 +1,817 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='REFUND_SELF_DESTRUCT', ctx=Store())], + value=Constant(value=24000)), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RETURN_DATA_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_FAST_STEP', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLAKE2_PER_ROUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COLD_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2100)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_WARM_ACCESS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=100)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_left', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='memory_cost', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='extra_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='call_stipend', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Expr( + value=Constant(value='\n Calculates the MessageCallGas (cost and stipend) for\n executing call Opcodes.\n\n Parameters\n ----------\n value:\n The amount of `ETH` that needs to be transferred.\n gas :\n The amount of gas provided to the message-call.\n gas_left :\n The amount of gas left in the current frame.\n memory_cost :\n The amount needed to extend the memory in the current frame.\n extra_gas :\n The amount of gas needed for transferring value + creating a new\n account inside a message call.\n call_stipend :\n The amount of stipend provided to a message call to execute code while\n transferring value(ETH).\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='call_stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='call_stipend', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='extra_gas', ctx=Load()), + op=Add(), + right=Name(id='memory_cost', ctx=Load()))]), + body=[ + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='gas', ctx=Load()), + Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='gas_left', ctx=Load()), + op=Sub(), + right=Name(id='memory_cost', ctx=Load())), + op=Sub(), + right=Name(id='extra_gas', ctx=Load()))], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load())), + FunctionDef( + name='max_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the maximum gas that is allowed for making a message call\n\n Parameters\n ----------\n gas :\n The amount of gas provided to the message-call.\n\n Returns\n -------\n max_allowed_message_call_gas: `ethereum.base_types.Uint`\n The maximum gas allowed for making the message-call.\n ')), + Return( + value=BinOp( + left=Name(id='gas', ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='gas', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]))))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/gas.v b/coq/ethereum/berlin/vm/gas.v new file mode 100644 index 0000000000..1ff33a2caf --- /dev/null +++ b/coq/ethereum/berlin/vm/gas.v @@ -0,0 +1,171 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (value : U256) (gas : Uint) (gas_left : Uint) (memory_cost : Uint) (extra_gas : Uint) (call_stipend : Uint) : M MessageCallGas := + (* + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "gas" [[ + M.get_local ~(| "min" |) ~(| + gas, + M.get_local ~(| "max_message_call_gas" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition max_message_call_gas (gas : Uint) : M Uint := + (* + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/vm/instructions/__init__.ast b/coq/ethereum/berlin/vm/instructions/__init__.ast new file mode 100644 index 0000000000..4f4c60bb9b --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/__init__.ast @@ -0,0 +1,1780 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='SHL', ctx=Store())], + value=Constant(value=27)), + Assign( + targets=[ + Name(id='SHR', ctx=Store())], + value=Constant(value=28)), + Assign( + targets=[ + Name(id='SAR', ctx=Store())], + value=Constant(value=29)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='RETURNDATASIZE', ctx=Store())], + value=Constant(value=61)), + Assign( + targets=[ + Name(id='RETURNDATACOPY', ctx=Store())], + value=Constant(value=62)), + Assign( + targets=[ + Name(id='EXTCODEHASH', ctx=Store())], + value=Constant(value=63)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='DIFFICULTY', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='CHAINID', ctx=Store())], + value=Constant(value=70)), + Assign( + targets=[ + Name(id='SELFBALANCE', ctx=Store())], + value=Constant(value=71)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='CREATE2', ctx=Store())], + value=Constant(value=245)), + Assign( + targets=[ + Name(id='STATICCALL', ctx=Store())], + value=Constant(value=250)), + Assign( + targets=[ + Name(id='REVERT', ctx=Store())], + value=Constant(value=253)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SAR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIFFICULTY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CHAINID', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODEHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFBALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STATICCALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='REVERT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE2', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shl', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shr', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_sar', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodehash', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='self_balance', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='staticcall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='revert', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create2', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/instructions/__init__.v b/coq/ethereum/berlin/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/berlin/vm/instructions/arithmetic.ast b/coq/ethereum/berlin/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/instructions/arithmetic.v b/coq/ethereum/berlin/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..1dd92520ff --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/berlin/vm/instructions/bitwise.ast b/coq/ethereum/berlin/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..b72397f0ec --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/bitwise.ast @@ -0,0 +1,751 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shl', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift left (SHL) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='value', ctx=Load()), + op=LShift(), + right=Name(id='shift', ctx=Load())), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]))], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shr', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift right (SHR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_sar', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Arithmetic shift right (SAR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='signed_value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=256)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + BinOp( + left=Name(id='signed_value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load()))], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='signed_value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load()))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/instructions/bitwise.v b/coq/ethereum/berlin/vm/instructions/bitwise.v new file mode 100644 index 0000000000..86dded2c4e --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/bitwise.v @@ -0,0 +1,309 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shl (evm : Evm) : M unit := + (* + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shr (evm : Evm) : M unit := + (* + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_sar (evm : Evm) : M unit := + (* + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + M.get_local ~(| "int" |) ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "signed_value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/berlin/vm/instructions/block.ast b/coq/ethereum/berlin/vm/instructions/block.ast new file mode 100644 index 0000000000..b9ccb3290b --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/block.ast @@ -0,0 +1,492 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's difficulty onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='chain_id', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the chain id onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/instructions/block.v b/coq/ethereum/berlin/vm/instructions/block.v new file mode 100644 index 0000000000..e8f098fa38 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/block.v @@ -0,0 +1,241 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition difficulty (evm : Evm) : M unit := + (* + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition chain_id (evm : Evm) : M unit := + (* + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/berlin/vm/instructions/comparison.ast b/coq/ethereum/berlin/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/instructions/comparison.v b/coq/ethereum/berlin/vm/instructions/comparison.v new file mode 100644 index 0000000000..4e409de78c --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/berlin/vm/instructions/control_flow.ast b/coq/ethereum/berlin/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/instructions/control_flow.v b/coq/ethereum/berlin/vm/instructions/control_flow.v new file mode 100644 index 0000000000..48cd13d5bb --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.exceptions. +Require ethereum.berlin.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/berlin/vm/instructions/environment.ast b/coq/ethereum/berlin/vm/instructions/environment.ast new file mode 100644 index 0000000000..ad41d4aca1 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/environment.ast @@ -0,0 +1,1773 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfBoundsRead')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_COLD_ACCOUNT_ACCESS'), + alias(name='GAS_COPY'), + alias(name='GAS_FAST_STEP'), + alias(name='GAS_RETURN_DATA_COPY'), + alias(name='GAS_VERY_LOW'), + alias(name='GAS_WARM_ACCESS'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_WARM_ACCESS', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the size of the return data buffer onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copies data from the return data buffer code to memory\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='return_data_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_RETURN_DATA_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='return_data_start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfBoundsRead', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load()), + slice=Slice( + lower=Name(id='return_data_start_position', ctx=Load()), + upper=BinOp( + left=Name(id='return_data_start_position', ctx=Load()), + op=Add(), + right=Name(id='size', ctx=Load()))), + ctx=Load())), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodehash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns the keccak256 hash of a contract’s bytecode\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='EMPTY_ACCOUNT', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codehash', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='self_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the current address to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_FAST_STEP', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/instructions/environment.v b/coq/ethereum/berlin/vm/instructions/environment.v new file mode 100644 index 0000000000..c8e0ae64a5 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/environment.v @@ -0,0 +1,700 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.berlin.fork_types. +Require ethereum.berlin.state. +Require ethereum.berlin.utils.address. +Require ethereum.berlin.vm.memory. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.exceptions. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatasize (evm : Evm) : M unit := + (* + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatacopy (evm : Evm) : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "return_data_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + (* TODO expression *) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodehash (evm : Evm) : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "account" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codehash" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition self_balance (evm : Evm) : M unit := + (* + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_FAST_STEP + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/berlin/vm/instructions/keccak.ast b/coq/ethereum/berlin/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/instructions/keccak.v b/coq/ethereum/berlin/vm/instructions/keccak.v new file mode 100644 index 0000000000..cd511b7d44 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.memory. +Require ethereum.berlin.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/berlin/vm/instructions/log.ast b/coq/ethereum/berlin/vm/instructions/log.ast new file mode 100644 index 0000000000..0ded0e04ba --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/log.ast @@ -0,0 +1,323 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/instructions/log.v b/coq/ethereum/berlin/vm/instructions/log.v new file mode 100644 index 0000000000..6726133595 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/log.v @@ -0,0 +1,79 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.berlin.blocks. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.exceptions. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.memory. +Require ethereum.berlin.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO statement *) + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/berlin/vm/instructions/memory.ast b/coq/ethereum/berlin/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/instructions/memory.v b/coq/ethereum/berlin/vm/instructions/memory.v new file mode 100644 index 0000000000..a06afeeafb --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.memory. +Require ethereum.berlin.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/berlin/vm/instructions/stack.ast b/coq/ethereum/berlin/vm/instructions/stack.ast new file mode 100644 index 0000000000..95cfc0b6cf --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/stack.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/instructions/stack.v b/coq/ethereum/berlin/vm/instructions/stack.v new file mode 100644 index 0000000000..ad3f28a6bd --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/stack.v @@ -0,0 +1,153 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.exceptions. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/berlin/vm/instructions/storage.ast b/coq/ethereum/berlin/vm/instructions/storage.ast new file mode 100644 index 0000000000..68640a90a8 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/storage.ast @@ -0,0 +1,551 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='get_storage_original'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_STIPEND'), + alias(name='GAS_COLD_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='GAS_WARM_ACCESS'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_SLOAD', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='get_storage_original', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + If( + test=Compare( + left=Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_COLD_SLOAD', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='current_value', ctx=Load())]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())])]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_COLD_SLOAD', ctx=Load())))])], + orelse=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))]), + If( + test=Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='GAS_STORAGE_SET', ctx=Load()), + op=Sub(), + right=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + keywords=[]))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_COLD_SLOAD', ctx=Load())), + op=Sub(), + right=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + keywords=[]))])], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/instructions/storage.v b/coq/ethereum/berlin/vm/instructions/storage.v new file mode 100644 index 0000000000..753df96ca4 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/storage.v @@ -0,0 +1,121 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.berlin.state. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.exceptions. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "original_value" [[ + state.get_storage_original ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "gas_cost" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/berlin/vm/instructions/system.ast b/coq/ethereum/berlin/vm/instructions/system.ast new file mode 100644 index 0000000000..46f89cee47 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/system.ast @@ -0,0 +1,2962 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='is_account_alive'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='compute_create2_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='Revert'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_VALUE'), + alias(name='GAS_COLD_ACCOUNT_ACCESS'), + alias(name='GAS_CREATE'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='GAS_NEW_ACCOUNT'), + alias(name='GAS_SELF_DESTRUCT'), + alias(name='GAS_SELF_DESTRUCT_NEW_ACCOUNT'), + alias(name='GAS_WARM_ACCESS'), + alias(name='GAS_ZERO'), + alias(name='REFUND_SELF_DESTRUCT'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas'), + alias(name='max_message_call_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='generic_create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='endowment', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='contract_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='memory_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Core logic used by the `CREATE*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='contract_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='create_message_gas', ctx=Load())), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='is_static', + value=Constant(value=False)), + keyword( + arg='accessed_addresses', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create2', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Creates a new account with associated code.\n\n It's similar to CREATE opcode except that the address of new account\n depends on the init_code instead of the nonce of sender.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ")), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='salt', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='call_data_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='call_data_words', ctx=Load()))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_create2_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='salt', ctx=Load()), + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_staticcall', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=IfExp( + test=Name(id='is_staticcall', ctx=Load()), + body=Constant(value=True), + orelse=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()))), + keyword( + arg='accessed_addresses', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='to', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=BoolOp( + op=Or(), + values=[ + Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[]), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='access_gas_cost', ctx=Load()), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='code_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=Name(id='access_gas_cost', ctx=Load()), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SELF_DESTRUCT', ctx=Load())), + If( + test=Compare( + left=Name(id='beneficiary', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[])), + Compare( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='refunded_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load())), + While( + test=Compare( + left=Name(id='parent_evm', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='refunded_accounts', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='originator', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='refunded_accounts', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Name(id='REFUND_SELF_DESTRUCT', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='code_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='access_gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='staticcall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='to', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='access_gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='revert', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop execution and revert state changes, without consuming all provided gas\n and also has the ability to return a reason\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Name(id='output', ctx=Load())], + keywords=[])), + Raise( + exc=Name(id='Revert', ctx=Load())), + Pass()], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/instructions/system.v b/coq/ethereum/berlin/vm/instructions/system.v new file mode 100644 index 0000000000..273ded3dc3 --- /dev/null +++ b/coq/ethereum/berlin/vm/instructions/system.v @@ -0,0 +1,787 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.berlin.fork_types. +Require ethereum.berlin.state. +Require ethereum.berlin.utils.address. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.exceptions. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.memory. +Require ethereum.berlin.vm.stack. + +Definition generic_create (evm : Evm) (endowment : U256) (contract_address : Address) (memory_start_position : U256) (memory_size : U256) : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "add" |) ~(| + contract_address + |) ]] in + do* M.assign "create_message_gas" [[ + gas.max_message_call_gas ~(| + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) in + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_local ~(| "create_message_gas" |) + ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_start_position, + memory_size + |) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_create_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition create2 (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "salt" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "call_data_words" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_create2_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "salt" |), + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (is_staticcall : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_SELF_DESTRUCT in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "refunded_accounts" [[ + M.get_field ~(| evm, "accounts_to_delete" |) in + ]] in + do* M.assign "parent_evm" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "parent_evm" |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + M.get_local ~(| "access_gas_cost" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition staticcall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + M.get_local ~(| "access_gas_cost" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "to" |), + M.get_local ~(| "to" |), + True, + True, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition revert (evm : Evm) : M unit := + (* + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "output" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/vm/interpreter.ast b/coq/ethereum/berlin/vm/interpreter.ast new file mode 100644 index 0000000000..80b2cb6334 --- /dev/null +++ b/coq/ethereum/berlin/vm/interpreter.ast @@ -0,0 +1,1149 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Iterable'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='increment_nonce'), + alias(name='mark_account_created'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidOpcode'), + alias(name='OutOfGasError'), + alias(name='Revert'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_CODE_SIZE', ctx=Store())], + value=Constant(value=24576)), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `touched_accounts`: Accounts that have been touched.\n 6. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='touched_accounts', + value=Name(id='touched_accounts', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.berlin.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='mark_account_created', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_CODE_SIZE', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.berlin.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='touched_accounts', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='return_data', + value=Constant(value=b'')), + keyword( + arg='error', + value=Constant(value=None)), + keyword( + arg='accessed_addresses', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='accessed_addresses', + ctx=Load())), + keyword( + arg='accessed_storage_keys', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))]), + ExceptHandler( + type=Name(id='Revert', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/interpreter.v b/coq/ethereum/berlin/vm/interpreter.v new file mode 100644 index 0000000000..1e58adada8 --- /dev/null +++ b/coq/ethereum/berlin/vm/interpreter.v @@ -0,0 +1,173 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.berlin.blocks. +Require ethereum.berlin.fork_types. +Require ethereum.berlin.state. +Require ethereum.berlin.vm. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.precompiled_contracts.mapping. +Require ethereum.berlin.vm.__init__. +Require ethereum.berlin.vm.exceptions. +Require ethereum.berlin.vm.instructions. +Require ethereum.berlin.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.berlin.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.mark_account_created ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.berlin.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/vm/memory.ast b/coq/ethereum/berlin/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/berlin/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/memory.v b/coq/ethereum/berlin/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/berlin/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/__init__.ast b/coq/ethereum/berlin/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..bb9991907f --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS'), + Constant(value='MODEXP_ADDRESS'), + Constant(value='ALT_BN128_ADD_ADDRESS'), + Constant(value='ALT_BN128_MUL_ADDRESS'), + Constant(value='ALT_BN128_PAIRING_CHECK_ADDRESS'), + Constant(value='BLAKE2F_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[])), + Assign( + targets=[ + Name(id='MODEXP_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x05')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x06')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x07')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x08')], + keywords=[])), + Assign( + targets=[ + Name(id='BLAKE2F_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x09')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/__init__.v b/coq/ethereum/berlin/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..693661609c --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.berlin.utils.hexadecimal. diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/alt_bn128.ast b/coq/ethereum/berlin/vm/precompiled_contracts/alt_bn128.ast new file mode 100644 index 0000000000..f6f077419c --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/alt_bn128.ast @@ -0,0 +1,913 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ALT_BN128 CONTRACTS\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ALT_BN128 precompiled contracts.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.alt_bn128', + names=[ + alias(name='ALT_BN128_CURVE_ORDER'), + alias(name='ALT_BN128_PRIME'), + alias(name='BNF'), + alias(name='BNF2'), + alias(name='BNF12'), + alias(name='BNP'), + alias(name='BNP2'), + alias(name='pairing')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=2), + FunctionDef( + name='alt_bn128_add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 addition precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=150)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load()), + Name(id='x1_value', ctx=Load()), + Name(id='y1_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='p1', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x1_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y1_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=BinOp( + left=Name(id='p0', ctx=Load()), + op=Add(), + right=Name(id='p1', ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 multiplication precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6000)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='n', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='p0', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='n', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_pairing_check', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 pairing check precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=34000), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))), + op=Add(), + right=Constant(value=45000))], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=192)), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='values', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=Name(id='j', ctx=Load()))), + upper=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=BinOp( + left=Name(id='j', ctx=Load()), + op=Add(), + right=Constant(value=1))))), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='values', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=Call( + func=Name(id='BNP2', ctx=Load()), + args=[ + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=3), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=2), + ctx=Load())], + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=5), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=4), + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='OutOfGasError', ctx=Load()), + args=[], + keywords=[]))])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='p', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='q', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='p', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + Compare( + left=Name(id='q', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='result', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='pairing', ctx=Load()), + args=[ + Name(id='q', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[])))], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='result', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/berlin/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000000..15ae619b27 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,226 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.alt_bn128. +Require ethereum.berlin.vm. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.memory. +Require ethereum.berlin.vm.exceptions. + +Definition alt_bn128_add (evm : Evm) : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 150 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "x1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x1_bytes" |) + |) + |) in + ]] in + do* M.assign "y1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y1_bytes" |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + (* TODO expression *) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_mul (evm : Evm) : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 6000 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "n" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + M.get_field ~(| M.get_local ~(| "p0" |), "mul_by" |) ~(| + M.get_local ~(| "n" |) + |) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_pairing_check (evm : Evm) : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + (* TODO expression *) + |) + |) ]] in + (* TODO statement *) + do* M.assign "result" [[ + M.get_field ~(| ethereum.crypto.alt_bn128.BNF12, "from_int" |) ~(| + 1 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/blake2f.ast b/coq/ethereum/berlin/vm/precompiled_contracts/blake2f.ast new file mode 100644 index 0000000000..03747962f0 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/blake2f.ast @@ -0,0 +1,137 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `Blake2` precompiled contract.\n')), + ImportFrom( + module='ethereum.crypto.blake2', + names=[ + alias(name='Blake2b')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BLAKE2_PER_ROUND'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidParameter')], + level=2), + FunctionDef( + name='blake2f', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the Blake2 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Constant(value=213)]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='blake2b', ctx=Store())], + value=Call( + func=Name(id='Blake2b', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='rounds', ctx=Store()), + Name(id='h', ctx=Store()), + Name(id='m', ctx=Store()), + Name(id='t_0', ctx=Store()), + Name(id='t_1', ctx=Store()), + Name(id='f', ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='get_blake2_parameters', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_BLAKE2_PER_ROUND', ctx=Load()), + op=Mult(), + right=Name(id='rounds', ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=Name(id='f', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + List( + elts=[ + Constant(value=0), + Constant(value=1)], + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='compress', + ctx=Load()), + args=[ + Name(id='rounds', ctx=Load()), + Name(id='h', ctx=Load()), + Name(id='m', ctx=Load()), + Name(id='t_0', ctx=Load()), + Name(id='t_1', ctx=Load()), + Name(id='f', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/blake2f.v b/coq/ethereum/berlin/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000000..ac2f5936a2 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,46 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +*) + +Require ethereum.crypto.blake2. +Require ethereum.berlin.vm. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.exceptions. + +Definition blake2f (evm : Evm) : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + (* TODO statement *) + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| + + |) in + ]] in + (* TODO assignment *) + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/berlin/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/berlin/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..cadaeda618 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.berlin.vm. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/identity.ast b/coq/ethereum/berlin/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/identity.v b/coq/ethereum/berlin/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..ae81e0d581 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.berlin.vm. +Require ethereum.berlin.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/mapping.ast b/coq/ethereum/berlin/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..cec40e5736 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ALT_BN128_ADD_ADDRESS'), + alias(name='ALT_BN128_MUL_ADDRESS'), + alias(name='ALT_BN128_PAIRING_CHECK_ADDRESS'), + alias(name='BLAKE2F_ADDRESS'), + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='MODEXP_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='alt_bn128', + names=[ + alias(name='alt_bn128_add'), + alias(name='alt_bn128_mul'), + alias(name='alt_bn128_pairing_check')], + level=1), + ImportFrom( + module='blake2f', + names=[ + alias(name='blake2f')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='modexp', + names=[ + alias(name='modexp')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load()), + Name(id='MODEXP_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Load()), + Name(id='BLAKE2F_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load()), + Name(id='modexp', ctx=Load()), + Name(id='alt_bn128_add', ctx=Load()), + Name(id='alt_bn128_mul', ctx=Load()), + Name(id='alt_bn128_pairing_check', ctx=Load()), + Name(id='blake2f', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/mapping.v b/coq/ethereum/berlin/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..e296eda824 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/mapping.v @@ -0,0 +1,25 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.berlin.fork_types. +Require ethereum.berlin.vm.precompiled_contracts.__init__. +Require ethereum.berlin.vm.precompiled_contracts.alt_bn128. +Require ethereum.berlin.vm.precompiled_contracts.blake2f. +Require ethereum.berlin.vm.precompiled_contracts.ecrecover. +Require ethereum.berlin.vm.precompiled_contracts.identity. +Require ethereum.berlin.vm.precompiled_contracts.modexp. +Require ethereum.berlin.vm.precompiled_contracts.ripemd160. +Require ethereum.berlin.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/modexp.ast b/coq/ethereum/berlin/vm/precompiled_contracts/modexp.ast new file mode 100644 index 0000000000..42ecfa223f --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/modexp.ast @@ -0,0 +1,638 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `MODEXP` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + Assign( + targets=[ + Name(id='GQUADDIVISOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + FunctionDef( + name='modexp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and.\n `modulus`. The return value is the same length as the modulus.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='base_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_start', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Add(), + right=Name(id='base_length', ctx=Load()))), + Assign( + targets=[ + Name(id='exp_head', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Call( + func=Name(id='min', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='gas_cost', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load()), + Name(id='exp_length', ctx=Load()), + Name(id='exp_head', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='base_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='modulus_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Name(id='base_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_start', ctx=Store())], + value=BinOp( + left=Name(id='exp_start', ctx=Load()), + op=Add(), + right=Name(id='exp_length', ctx=Load()))), + Assign( + targets=[ + Name(id='modulus', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='modulus_start', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='modulus', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'\x00')], + keywords=[]), + op=Mult(), + right=Name(id='modulus_length', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exp', ctx=Load()), + Name(id='modulus', ctx=Load())], + keywords=[]), + attr='to_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[]), + Constant(value='big')], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='complexity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Estimate the complexity of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n Returns\n -------\n\n complexity : `Uint`\n Complexity of performing the operation.\n ')), + Assign( + targets=[ + Name(id='max_length', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load())], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Return( + value=BinOp( + left=Name(id='words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='iterations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the number of iterations required to perform a modular\n exponentiation.\n\n Parameters\n ----------\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n iterations : `Uint`\n Number of iterations.\n ')), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + Compare( + left=Name(id='exponent_head', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='bit_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='bit_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='bit_length', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Name(id='bit_length', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='length_part', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])))), + Assign( + targets=[ + Name(id='bits_part', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='bits_part', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='bits_part', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=BinOp( + left=Name(id='length_part', ctx=Load()), + op=Add(), + right=Name(id='bits_part', ctx=Load())))])]), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='count', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the gas cost of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n gas_cost : `Uint`\n Gas required for performing the operation.\n ')), + Assign( + targets=[ + Name(id='multiplication_complexity', ctx=Store())], + value=Call( + func=Name(id='complexity', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='iteration_count', ctx=Store())], + value=Call( + func=Name(id='iterations', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load()), + Name(id='exponent_head', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cost', ctx=Store())], + value=BinOp( + left=Name(id='multiplication_complexity', ctx=Load()), + op=Mult(), + right=Name(id='iteration_count', ctx=Load()))), + AugAssign( + target=Name(id='cost', ctx=Store()), + op=FloorDiv(), + value=Name(id='GQUADDIVISOR', ctx=Load())), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[]), + Name(id='cost', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/modexp.v b/coq/ethereum/berlin/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000000..760522f59c --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/modexp.v @@ -0,0 +1,236 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.berlin.vm. +Require ethereum.berlin.vm.gas. +Require ethereum.berlin.vm.memory. + +Definition modexp (evm : Evm) : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "base_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "modulus_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "exp_head" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "min" |) ~(| + ethereum_types.numeric.U256 ~(| + 32 + |), + M.get_local ~(| "exp_length" |) + |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) ~(| + M.get_local ~(| "base_length" |), + M.get_local ~(| "modulus_length" |), + M.get_local ~(| "exp_length" |), + M.get_local ~(| "exp_head" |) + |) + |) ]] in + (* TODO statement *) + do* M.assign "base" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + M.get_local ~(| "base_length" |) + |) + |) in + ]] in + do* M.assign "exp" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "exp_length" |) + |) + |) in + ]] in + do* M.assign "modulus_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "modulus" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "modulus_start" |), + M.get_local ~(| "modulus_length" |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := + (* + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + *) + do* M.assign "max_length" [[ + M.get_local ~(| "max" |) ~(| + ethereum_types.numeric.Uint ~(| + base_length + |), + ethereum_types.numeric.Uint ~(| + modulus_length + |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition gas_cost (base_length : U256) (modulus_length : U256) (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + *) + do* M.assign "multiplication_complexity" [[ + M.get_local ~(| "complexity" |) ~(| + base_length, + modulus_length + |) in + ]] in + do* M.assign "iteration_count" [[ + M.get_local ~(| "iterations" |) ~(| + exponent_length, + exponent_head + |) in + ]] in + do* M.assign "cost" [[ + (* TODO expression *) in + ]] in + do* M.aug_assign [[ M.get_local ~(| "cost" |) ]] [[ + M.get_local ~(| "GQUADDIVISOR" |) + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/berlin/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/berlin/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/sha256.ast b/coq/ethereum/berlin/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/precompiled_contracts/sha256.v b/coq/ethereum/berlin/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/berlin/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/berlin/vm/runtime.ast b/coq/ethereum/berlin/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/berlin/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/runtime.v b/coq/ethereum/berlin/vm/runtime.v new file mode 100644 index 0000000000..4553022893 --- /dev/null +++ b/coq/ethereum/berlin/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.berlin.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/berlin/vm/stack.ast b/coq/ethereum/berlin/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/berlin/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/berlin/vm/stack.v b/coq/ethereum/berlin/vm/stack.v new file mode 100644 index 0000000000..e104e7225e --- /dev/null +++ b/coq/ethereum/berlin/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.berlin.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/__init__.ast b/coq/ethereum/byzantium/__init__.ast new file mode 100644 index 0000000000..0913465362 --- /dev/null +++ b/coq/ethereum/byzantium/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe Byzantium fork reduces the mining rewards, delays the difficulty bomb,\nlets contracts make non-state-changing calls to other contracts, and adds\ncryptographic primitives for layer 2 scaling.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=4370000)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/__init__.v b/coq/ethereum/byzantium/__init__.v new file mode 100644 index 0000000000..7d892ebede --- /dev/null +++ b/coq/ethereum/byzantium/__init__.v @@ -0,0 +1,8 @@ +(* Generated *) +(* +The Byzantium fork reduces the mining rewards, delays the difficulty bomb, +lets contracts make non-state-changing calls to other contracts, and adds +cryptographic primitives for layer 2 scaling. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/byzantium/blocks.ast b/coq/ethereum/byzantium/blocks.ast new file mode 100644 index 0000000000..bcca95bdaa --- /dev/null +++ b/coq/ethereum/byzantium/blocks.ast @@ -0,0 +1,218 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mix_digest', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='succeeded', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/blocks.v b/coq/ethereum/byzantium/blocks.v new file mode 100644 index 0000000000..54b88d4b70 --- /dev/null +++ b/coq/ethereum/byzantium/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.byzantium.fork_types. +Require ethereum.byzantium.transactions. diff --git a/coq/ethereum/byzantium/bloom.ast b/coq/ethereum/byzantium/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/byzantium/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/bloom.v b/coq/ethereum/byzantium/bloom.v new file mode 100644 index 0000000000..93ebeb1829 --- /dev/null +++ b/coq/ethereum/byzantium/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.byzantium.blocks. +Require ethereum.byzantium.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/fork.ast b/coq/ethereum/byzantium/fork.ast new file mode 100644 index 0000000000..c869ebcbad --- /dev/null +++ b/coq/ethereum/byzantium/fork.ast @@ -0,0 +1,3186 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.ethash', + names=[ + alias(name='dataset_size'), + alias(name='generate_cache'), + alias(name='hashimoto_light')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty'), + alias(name='create_ether'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='Transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BLOCK_REWARD', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=3), + op=Mult(), + right=BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=18)))], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=131072)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_OMMER_DEPTH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='BOMB_DELAY_BLOCKS', ctx=Store())], + value=Constant(value=3000000)), + Assign( + targets=[ + Name(id='EMPTY_OMMER_HASH', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List(elts=[], ctx=Load())], + keywords=[])], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='validate_ommers', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='chain', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='chain', ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + Assign( + targets=[ + Name(id='parent_has_ommers', ctx=Store())], + value=Compare( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='EMPTY_OMMER_HASH', ctx=Load())])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_difficulty', ctx=Store())], + value=Call( + func=Name(id='calculate_block_difficulty', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Name(id='parent_has_ommers', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_difficulty', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='validate_proof_of_work', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generate_header_hash_for_pow', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate rlp hash of the header which is to be used for Proof-of-Work\n verification.\n\n In other words, the PoW artefacts `mix_digest` and `nonce` are ignored\n while calculating this hash.\n\n A particular PoW is valid for a single hash, that hash is computed by\n this function. The `nonce` and `mix_digest` are omitted from this hash\n because they are being changed by miners in their search for a sufficient\n proof-of-work.\n\n Parameters\n ----------\n header :\n The header object for which the hash is to be generated.\n\n Returns\n -------\n hash : `Hash32`\n The PoW valid rlp hash of the passed in header.\n ')), + Assign( + targets=[ + Name(id='header_data_without_pow_artefacts', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='state_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='transactions_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='receipt_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='bloom', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='header_data_without_pow_artefacts', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='validate_proof_of_work', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the Proof of Work constraints.\n\n In order to verify that a miner's proof-of-work is valid for a block, a\n ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``\n hash function. The mix digest is a hash of the header and the nonce that\n is passed through and it confirms whether or not proof-of-work was done\n on the correct block. The result is the actual hash value of the block.\n\n Parameters\n ----------\n header :\n Header of interest.\n ")), + Assign( + targets=[ + Name(id='header_hash', ctx=Store())], + value=Call( + func=Name(id='generate_header_hash_for_pow', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache', ctx=Store())], + value=Call( + func=Name(id='generate_cache', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='mix_digest', ctx=Store()), + Name(id='result', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='hashimoto_light', ctx=Load()), + args=[ + Name(id='header_hash', ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + Name(id='cache', ctx=Load()), + Call( + func=Name(id='dataset_size', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='mix_digest', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='mix_digest', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='limit', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='limit', ctx=Load()), + op=FloorDiv(), + right=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n gas_available :\n The gas remaining in the block.\n chain_id :\n The ID of the current chain.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + Return( + value=Name(id='sender_address', ctx=Load()))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='error', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n error :\n Error in the top level frame of the transaction, if any.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='succeeded', + value=Compare( + left=Name(id='error', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)])), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + Return( + value=Name(id='receipt', ctx=Load()))], + decorator_list=[], + returns=Name(id='Receipt', ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='block_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n block_difficulty :\n Difficulty of the block.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='transactions', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='tx', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='gas_available', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='gas_price', + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='difficulty', + value=Name(id='block_difficulty', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store()), + Name(id='error', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='error', ctx=Load()), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='pay_rewards', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='block_number', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='ommers', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='validate_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='block_header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the ommers mentioned in the block.\n\n An ommer block is a block that wasn't canonically added to the\n blockchain because it wasn't validated as fast as the canonical block\n but was mined at the same time.\n\n To be considered valid, the ommers must adhere to the rules defined in\n the Ethereum protocol. The maximum amount of ommers is 2 per block and\n there cannot be duplicate ommers in a block. Many of the other ommer\n constraints are listed in the in-line comments of this function.\n\n Parameters\n ----------\n ommers :\n List of ommers mentioned in the current block.\n block_header:\n The header of current block.\n chain :\n History and current state.\n ")), + Assign( + targets=[ + Name(id='block_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='block_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='ommers_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return()], + orelse=[]), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + op=Sub(), + right=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Name(id='ommer', ctx=Load()), + Name(id='ommer_parent_header', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=2)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommers_hashes', ctx=Store())], + value=ListComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + ifs=[], + is_async=0)])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[])], + keywords=[])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_canonical_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=BinOp( + left=Name(id='MAX_OMMER_DEPTH', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + ctx=Load())), + Assign( + targets=[ + Name(id='recent_canonical_block_hashes', ctx=Store())], + value=SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='recent_ommers_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + simple=1), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='recent_ommers_hashes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='recent_ommers_hashes', ctx=Load()), + attr='union', + ctx=Load()), + args=[ + SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='ommer_index', ctx=Store()), + Name(id='ommer', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='ommer_hash', ctx=Store())], + value=Subscript( + value=Name(id='ommers_hashes', ctx=Load()), + slice=Name(id='ommer_index', ctx=Load()), + ctx=Load())), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='block_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_ommers_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='ommer_age', ctx=Load())]), + Compare( + left=Name(id='ommer_age', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_OMMER_DEPTH', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='parent_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pay_rewards', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pay rewards to the block miner as well as the ommers miners.\n\n The miner of the canonical block is rewarded with the predetermined\n block reward, ``BLOCK_REWARD``, plus a variable award based off of the\n number of ommer blocks that were mined around the same time, and included\n in the canonical block's header. An ommer block is a block that wasn't\n added to the canonical blockchain because it wasn't validated as fast as\n the accepted block but was mined at the same time. Although not all blocks\n that are mined are added to the canonical chain, miners are still paid a\n reward for their efforts. This reward is called an ommer reward and is\n calculated based on the number associated with the ommer block that they\n mined.\n\n Parameters\n ----------\n state :\n Current account state.\n block_number :\n Position of the block within the chain.\n coinbase :\n Address of account which receives block reward and transaction fees.\n ommers :\n List of ommers mentioned in the current block.\n ")), + Assign( + targets=[ + Name(id='ommer_count', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='miner_reward', ctx=Store())], + value=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='ommer_count', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='miner_reward', ctx=Load())], + keywords=[])), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_number', ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='ommer_miner_reward', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Sub(), + right=Name(id='ommer_age', ctx=Load())), + op=Mult(), + right=Name(id='BLOCK_REWARD', ctx=Load())), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='ommer_miner_reward', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + If( + test=Compare( + left=Name(id='coinbase_balance_after_mining_fee', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]))], + orelse=[])]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='error', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Name(id='TX_CREATE_COST', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='v', ctx=Store()), + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=28)])]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash_pre155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='chain_id_x2', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=36)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[])), + op=Sub(), + right=Name(id='chain_id_x2', ctx=Load())), + Call( + func=Name(id='signing_hash_155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])], + keywords=[]))]), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash_pre155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a legacy (pre EIP 155) signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 155 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n The id of the current chain.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='chain_id', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_has_ommers', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes difficulty of a block using its header and parent header.\n\n The difficulty is determined by the time the block was created after its\n parent. The ``offset`` is calculated using the parent block's difficulty,\n ``parent_difficulty``, and the timestamp between blocks. This offset is\n then added to the parent difficulty and is stored as the ``difficulty``\n variable. If the time between the block and its parent is too short, the\n offset will result in a positive number thus making the sum of\n ``parent_difficulty`` and ``offset`` to be a greater value in order to\n avoid mass forking. But, if the time is long enough, then the offset\n results in a negative value making the block less difficult than\n its parent.\n\n The base standard for a block's difficulty is the predefined value\n set for the genesis block since it has no parent. So, a block\n can't be less difficult than the genesis block, therefore each block's\n difficulty is set to the maximum value between the calculated\n difficulty and the ``GENESIS_DIFFICULTY``.\n\n Parameters\n ----------\n block_number :\n Block number of the block.\n block_timestamp :\n Timestamp of the block.\n parent_timestamp :\n Timestamp of the parent block.\n parent_difficulty :\n difficulty of the parent block.\n parent_has_ommers:\n does the parent have ommers.\n\n Returns\n -------\n difficulty : `ethereum.base_types.Uint`\n Computed difficulty for a block.\n ")), + Assign( + targets=[ + Name(id='offset', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=2048)), + op=Mult(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=IfExp( + test=Name(id='parent_has_ommers', ctx=Load()), + body=Constant(value=2), + orelse=Constant(value=1)), + op=Sub(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_timestamp', ctx=Load()), + op=Sub(), + right=Name(id='parent_timestamp', ctx=Load()))], + keywords=[]), + op=FloorDiv(), + right=Constant(value=9))), + UnaryOp( + op=USub(), + operand=Constant(value=99))], + keywords=[]))), + Assign( + targets=[ + Name(id='difficulty', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='offset', ctx=Load()))), + Assign( + targets=[ + Name(id='num_bomb_periods', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='BOMB_DELAY_BLOCKS', ctx=Load())), + op=FloorDiv(), + right=Constant(value=100000)), + op=Sub(), + right=Constant(value=2))), + If( + test=Compare( + left=Name(id='num_bomb_periods', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='difficulty', ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Name(id='num_bomb_periods', ctx=Load())))], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='difficulty', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/fork.v b/coq/ethereum/byzantium/fork.v new file mode 100644 index 0000000000..8ddfd5df4d --- /dev/null +++ b/coq/ethereum/byzantium/fork.v @@ -0,0 +1,847 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.ethash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.byzantium.__init__. +Require ethereum.byzantium.blocks. +Require ethereum.byzantium.bloom. +Require ethereum.byzantium.fork_types. +Require ethereum.byzantium.state. +Require ethereum.byzantium.transactions. +Require ethereum.byzantium.trie. +Require ethereum.byzantium.utils.message. +Require ethereum.byzantium.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + do* [[ M.get_local ~(| "validate_ommers" |) ~(| + M.get_field ~(| block, "ommers" |), + M.get_field ~(| block, "header" |), + chain + |) ]] in + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "difficulty" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| block, "ommers" |), + M.get_field ~(| chain, "chain_id" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + do* M.assign "parent_has_ommers" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_difficulty" [[ + M.get_local ~(| "calculate_block_difficulty" |) ~(| + M.get_field ~(| header, "number" |), + M.get_field ~(| header, "timestamp" |), + M.get_field ~(| parent_header, "timestamp" |), + M.get_field ~(| parent_header, "difficulty" |), + M.get_local ~(| "parent_has_ommers" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| + header + |) ]] in + M.pure tt. + +Definition generate_header_hash_for_pow (header : Header) : M Hash32 := + (* + 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. + *) + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_proof_of_work (header : Header) : M unit := + (* + 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. + *) + do* M.assign "header_hash" [[ + M.get_local ~(| "generate_header_hash_for_pow" |) ~(| + header + |) in + ]] in + do* M.assign "cache" [[ + ethereum.ethash.generate_cache ~(| + M.get_field ~(| header, "number" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (gas_available : Uint) (chain_id : U64) : M Address := + (* + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (error : (* TODO type *)) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (block_gas_limit : Uint) (block_time : U256) (block_difficulty : Uint) (transactions : (* TODO type *)) (ommers : (* TODO type *)) (chain_id : U64) : M ApplyBodyOutput := + (* + 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.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "pay_rewards" |) ~(| + state, + block_number, + coinbase, + ommers + |) ]] in + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_ommers (ommers : (* TODO type *)) (block_header : Header) (chain : BlockChain) : M unit := + (* + 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. + *) + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_canonical_blocks" [[ + (* TODO expression *) in + ]] in + do* M.assign "recent_canonical_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition pay_rewards (state : State) (block_number : Uint) (coinbase : Address) (ommers : (* TODO type *)) : M unit := + (* + 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. + *) + do* M.assign "ommer_count" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + ommers + |) + |) in + ]] in + do* M.assign "miner_reward" [[ + (* TODO expression *) in + ]] in + do* [[ state.create_ether ~(| + state, + coinbase, + M.get_local ~(| "miner_reward" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + do* M.assign "gas_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_pre155 (tx : Transaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_155 (tx : Transaction) (chain_id : U64) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_block_difficulty (block_number : Uint) (block_timestamp : U256) (parent_timestamp : U256) (parent_difficulty : Uint) (parent_has_ommers : bool) : M Uint := + (* + 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. + *) + do* M.assign "offset" [[ + (* TODO expression *) in + ]] in + do* M.assign "difficulty" [[ + (* TODO expression *) in + ]] in + do* M.assign "num_bomb_periods" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/fork_types.ast b/coq/ethereum/byzantium/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/byzantium/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/fork_types.v b/coq/ethereum/byzantium/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/byzantium/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/state.ast b/coq/ethereum/byzantium/state.ast new file mode 100644 index 0000000000..e39d5427ff --- /dev/null +++ b/coq/ethereum/byzantium/state.ast @@ -0,0 +1,1500 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has zero nonce, empty code and zero balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_empty : `bool`\n True if if an account has zero nonce, empty code and zero balance,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_exists_and_is_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists and has zero nonce, empty code and zero\n balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n exists_and_is_empty : `bool`\n True if an account exists and has zero nonce, empty code and zero\n balance, False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='account', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_alive', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether is an account is both in the state and non empty.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_alive : `bool`\n True if the account is alive.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[ + Return( + value=UnaryOp( + op=Not(), + operand=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])])))])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add newly created ether to an account.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to which ether is added.\n amount:\n The amount of ether to be added to the account of interest.\n ')), + FunctionDef( + name='increase_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/state.v b/coq/ethereum/byzantium/state.v new file mode 100644 index 0000000000..79b91b8917 --- /dev/null +++ b/coq/ethereum/byzantium/state.v @@ -0,0 +1,562 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.byzantium.fork_types. +Require ethereum.byzantium.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_empty (state : State) (address : Address) : M bool := + (* + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition account_exists_and_is_empty (state : State) (address : Address) : M bool := + (* + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_alive (state : State) (address : Address) : M bool := + (* + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := + (* + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum/byzantium/transactions.ast b/coq/ethereum/byzantium/transactions.ast new file mode 100644 index 0000000000..19d5c9707f --- /dev/null +++ b/coq/ethereum/byzantium/transactions.ast @@ -0,0 +1,106 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + ClassDef( + name='Transaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/transactions.v b/coq/ethereum/byzantium/transactions.v new file mode 100644 index 0000000000..d4c75cb9b0 --- /dev/null +++ b/coq/ethereum/byzantium/transactions.v @@ -0,0 +1,13 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.byzantium.fork_types. diff --git a/coq/ethereum/byzantium/trie.ast b/coq/ethereum/byzantium/trie.ast new file mode 100644 index 0000000000..cf0cb62ead --- /dev/null +++ b/coq/ethereum/byzantium/trie.ast @@ -0,0 +1,1618 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.spurious_dragon', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.RLP`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/trie.v b/coq/ethereum/byzantium/trie.v new file mode 100644 index 0000000000..6b8953f256 --- /dev/null +++ b/coq/ethereum/byzantium/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/utils/__init__.ast b/coq/ethereum/byzantium/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/byzantium/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/utils/__init__.v b/coq/ethereum/byzantium/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/byzantium/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/byzantium/utils/address.ast b/coq/ethereum/byzantium/utils/address.ast new file mode 100644 index 0000000000..193185ad18 --- /dev/null +++ b/coq/ethereum/byzantium/utils/address.ast @@ -0,0 +1,139 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this byzantium version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `ethereum.byzantium.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/utils/address.v b/coq/ethereum/byzantium/utils/address.v new file mode 100644 index 0000000000..2a6eedadd5 --- /dev/null +++ b/coq/ethereum/byzantium/utils/address.v @@ -0,0 +1,75 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this byzantium version of +specification. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.byzantium.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.byzantium.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/utils/hexadecimal.ast b/coq/ethereum/byzantium/utils/hexadecimal.ast new file mode 100644 index 0000000000..73460a4b13 --- /dev/null +++ b/coq/ethereum/byzantium/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to\nByzantium types.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/utils/hexadecimal.v b/coq/ethereum/byzantium/utils/hexadecimal.v new file mode 100644 index 0000000000..5e558aa0c5 --- /dev/null +++ b/coq/ethereum/byzantium/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Byzantium types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.byzantium.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/utils/message.ast b/coq/ethereum/byzantium/utils/message.ast new file mode 100644 index 0000000000..490249559f --- /dev/null +++ b/coq/ethereum/byzantium/utils/message.ast @@ -0,0 +1,241 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this byzantium version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_static', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True), + Constant(value=False)]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n is_static:\n if True then it prevents all state-changing operations from being\n executed.\n\n Returns\n -------\n message: `ethereum.byzantium.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=Name(id='is_static', ctx=Load())), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/utils/message.v b/coq/ethereum/byzantium/utils/message.v new file mode 100644 index 0000000000..2bd42562f2 --- /dev/null +++ b/coq/ethereum/byzantium/utils/message.v @@ -0,0 +1,60 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this byzantium version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.byzantium.fork_types. +Require ethereum.byzantium.state. +Require ethereum.byzantium.vm. +Require ethereum.byzantium.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) (is_static : bool) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + + Returns + ------- + message: `ethereum.byzantium.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/__init__.ast b/coq/ethereum/byzantium/vm/__init__.ast new file mode 100644 index 0000000000..de465cd184 --- /dev/null +++ b/coq/ethereum/byzantium/vm/__init__.ast @@ -0,0 +1,509 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty')], + level=2), + ImportFrom( + module='precompiled_contracts', + names=[ + alias(name='RIPEMD160_ADDRESS')], + level=1), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='is_static', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='return_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + If( + test=Compare( + left=Name(id='RIPEMD160_ADDRESS', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/__init__.v b/coq/ethereum/byzantium/vm/__init__.v new file mode 100644 index 0000000000..f946a758ce --- /dev/null +++ b/coq/ethereum/byzantium/vm/__init__.v @@ -0,0 +1,72 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.byzantium.blocks. +Require ethereum.byzantium.fork_types. +Require ethereum.byzantium.state. +Require ethereum.byzantium.vm.precompiled_contracts. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "touched_accounts" |), "update" |) ~(| + M.get_field ~(| child_evm, "touched_accounts" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + (* TODO statement *) + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/exceptions.ast b/coq/ethereum/byzantium/vm/exceptions.ast new file mode 100644 index 0000000000..ea06933e9c --- /dev/null +++ b/coq/ethereum/byzantium/vm/exceptions.ast @@ -0,0 +1,155 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='Revert', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised by the `REVERT` opcode.\n\n Unlike other EVM exceptions this does not result in the consumption of all\n gas.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='WriteInStaticContext', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt is made to modify the state while operating inside\n of a STATICCALL context.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfBoundsRead', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt was made to read data beyond the\n boundaries of the buffer.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/exceptions.v b/coq/ethereum/byzantium/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/byzantium/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/byzantium/vm/gas.ast b/coq/ethereum/byzantium/vm/gas.ast new file mode 100644 index 0000000000..30f813c093 --- /dev/null +++ b/coq/ethereum/byzantium/vm/gas.ast @@ -0,0 +1,809 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXTERNAL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BALANCE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=400)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='REFUND_SELF_DESTRUCT', ctx=Store())], + value=Constant(value=24000)), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RETURN_DATA_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_left', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='memory_cost', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='extra_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='call_stipend', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Expr( + value=Constant(value='\n Calculates the MessageCallGas (cost and stipend) for\n executing call Opcodes.\n\n Parameters\n ----------\n value:\n The amount of `ETH` that needs to be transferred.\n gas :\n The amount of gas provided to the message-call.\n gas_left :\n The amount of gas left in the current frame.\n memory_cost :\n The amount needed to extend the memory in the current frame.\n extra_gas :\n The amount of gas needed for transferring value + creating a new\n account inside a message call.\n call_stipend :\n The amount of stipend provided to a message call to execute code while\n transferring value(ETH).\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='call_stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='call_stipend', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='extra_gas', ctx=Load()), + op=Add(), + right=Name(id='memory_cost', ctx=Load()))]), + body=[ + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='gas', ctx=Load()), + Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='gas_left', ctx=Load()), + op=Sub(), + right=Name(id='memory_cost', ctx=Load())), + op=Sub(), + right=Name(id='extra_gas', ctx=Load()))], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load())), + FunctionDef( + name='max_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the maximum gas that is allowed for making a message call\n\n Parameters\n ----------\n gas :\n The amount of gas provided to the message-call.\n\n Returns\n -------\n max_allowed_message_call_gas: `ethereum.base_types.Uint`\n The maximum gas allowed for making the message-call.\n ')), + Return( + value=BinOp( + left=Name(id='gas', ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='gas', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]))))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/gas.v b/coq/ethereum/byzantium/vm/gas.v new file mode 100644 index 0000000000..05b1603559 --- /dev/null +++ b/coq/ethereum/byzantium/vm/gas.v @@ -0,0 +1,171 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (value : U256) (gas : Uint) (gas_left : Uint) (memory_cost : Uint) (extra_gas : Uint) (call_stipend : Uint) : M MessageCallGas := + (* + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "gas" [[ + M.get_local ~(| "min" |) ~(| + gas, + M.get_local ~(| "max_message_call_gas" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition max_message_call_gas (gas : Uint) : M Uint := + (* + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/instructions/__init__.ast b/coq/ethereum/byzantium/vm/instructions/__init__.ast new file mode 100644 index 0000000000..cc9bf820a9 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/__init__.ast @@ -0,0 +1,1696 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='RETURNDATASIZE', ctx=Store())], + value=Constant(value=61)), + Assign( + targets=[ + Name(id='RETURNDATACOPY', ctx=Store())], + value=Constant(value=62)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='DIFFICULTY', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='STATICCALL', ctx=Store())], + value=Constant(value=250)), + Assign( + targets=[ + Name(id='REVERT', ctx=Store())], + value=Constant(value=253)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIFFICULTY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STATICCALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='REVERT', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatacopy', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='staticcall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='revert', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/instructions/__init__.v b/coq/ethereum/byzantium/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/byzantium/vm/instructions/arithmetic.ast b/coq/ethereum/byzantium/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/instructions/arithmetic.v b/coq/ethereum/byzantium/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..58d1976d35 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/instructions/bitwise.ast b/coq/ethereum/byzantium/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..73dc9f4a45 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/bitwise.ast @@ -0,0 +1,418 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/instructions/bitwise.v b/coq/ethereum/byzantium/vm/instructions/bitwise.v new file mode 100644 index 0000000000..56886af9f9 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/bitwise.v @@ -0,0 +1,196 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/instructions/block.ast b/coq/ethereum/byzantium/vm/instructions/block.ast new file mode 100644 index 0000000000..cc66857e82 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/block.ast @@ -0,0 +1,437 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's difficulty onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/instructions/block.v b/coq/ethereum/byzantium/vm/instructions/block.v new file mode 100644 index 0000000000..86adb30702 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/block.v @@ -0,0 +1,213 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition difficulty (evm : Evm) : M unit := + (* + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/instructions/comparison.ast b/coq/ethereum/byzantium/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/instructions/comparison.v b/coq/ethereum/byzantium/vm/instructions/comparison.v new file mode 100644 index 0000000000..d76949b421 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/instructions/control_flow.ast b/coq/ethereum/byzantium/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/instructions/control_flow.v b/coq/ethereum/byzantium/vm/instructions/control_flow.v new file mode 100644 index 0000000000..34e896a17a --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.exceptions. +Require ethereum.byzantium.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/instructions/environment.ast b/coq/ethereum/byzantium/vm/instructions/environment.ast new file mode 100644 index 0000000000..d4bee1230f --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/environment.ast @@ -0,0 +1,1451 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfBoundsRead')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BALANCE'), + alias(name='GAS_BASE'), + alias(name='GAS_COPY'), + alias(name='GAS_EXTERNAL'), + alias(name='GAS_RETURN_DATA_COPY'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BALANCE', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_EXTERNAL', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_EXTERNAL', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the size of the return data buffer onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copies data from the return data buffer code to memory\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='return_data_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_RETURN_DATA_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='return_data_start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfBoundsRead', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load()), + slice=Slice( + lower=Name(id='return_data_start_position', ctx=Load()), + upper=BinOp( + left=Name(id='return_data_start_position', ctx=Load()), + op=Add(), + right=Name(id='size', ctx=Load()))), + ctx=Load())), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/instructions/environment.v b/coq/ethereum/byzantium/vm/instructions/environment.v new file mode 100644 index 0000000000..05d8a66949 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/environment.v @@ -0,0 +1,641 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.byzantium.state. +Require ethereum.byzantium.utils.address. +Require ethereum.byzantium.vm.memory. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.exceptions. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BALANCE + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_EXTERNAL + |) ]] in + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatasize (evm : Evm) : M unit := + (* + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatacopy (evm : Evm) : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "return_data_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + (* TODO expression *) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/instructions/keccak.ast b/coq/ethereum/byzantium/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/instructions/keccak.v b/coq/ethereum/byzantium/vm/instructions/keccak.v new file mode 100644 index 0000000000..3e0dae599a --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.memory. +Require ethereum.byzantium.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/instructions/log.ast b/coq/ethereum/byzantium/vm/instructions/log.ast new file mode 100644 index 0000000000..0ded0e04ba --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/log.ast @@ -0,0 +1,323 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/instructions/log.v b/coq/ethereum/byzantium/vm/instructions/log.v new file mode 100644 index 0000000000..cf94ab12d7 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/log.v @@ -0,0 +1,79 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.byzantium.blocks. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.exceptions. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.memory. +Require ethereum.byzantium.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO statement *) + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/instructions/memory.ast b/coq/ethereum/byzantium/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/instructions/memory.v b/coq/ethereum/byzantium/vm/instructions/memory.v new file mode 100644 index 0000000000..e929c50d1d --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.memory. +Require ethereum.byzantium.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/instructions/stack.ast b/coq/ethereum/byzantium/vm/instructions/stack.ast new file mode 100644 index 0000000000..95cfc0b6cf --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/stack.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/instructions/stack.v b/coq/ethereum/byzantium/vm/instructions/stack.v new file mode 100644 index 0000000000..461fe3f43d --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/stack.v @@ -0,0 +1,153 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.exceptions. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/instructions/storage.ast b/coq/ethereum/byzantium/vm/instructions/storage.ast new file mode 100644 index 0000000000..0857eefb7e --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/storage.ast @@ -0,0 +1,295 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_SLOAD', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_UPDATE', ctx=Load()))]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/instructions/storage.v b/coq/ethereum/byzantium/vm/instructions/storage.v new file mode 100644 index 0000000000..92a5d1c781 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/storage.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.byzantium.state. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.exceptions. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_SLOAD + |) ]] in + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/instructions/system.ast b/coq/ethereum/byzantium/vm/instructions/system.ast new file mode 100644 index 0000000000..08c20239a7 --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/system.ast @@ -0,0 +1,2516 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='is_account_alive'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='Revert'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL'), + alias(name='GAS_CALL_VALUE'), + alias(name='GAS_CREATE'), + alias(name='GAS_NEW_ACCOUNT'), + alias(name='GAS_SELF_DESTRUCT'), + alias(name='GAS_SELF_DESTRUCT_NEW_ACCOUNT'), + alias(name='GAS_ZERO'), + alias(name='REFUND_SELF_DESTRUCT'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas'), + alias(name='max_message_call_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='create_message_gas', ctx=Load())), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='is_static', + value=Constant(value=False)), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])])]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_staticcall', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=IfExp( + test=Name(id='is_staticcall', ctx=Load()), + body=Constant(value=True), + orelse=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()))), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[])]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SELF_DESTRUCT', ctx=Load())), + If( + test=BoolOp( + op=And(), + values=[ + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[])), + Compare( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='refunded_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load())), + While( + test=Compare( + left=Name(id='parent_evm', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='refunded_accounts', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='originator', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='refunded_accounts', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Name(id='REFUND_SELF_DESTRUCT', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='GAS_CALL', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='staticcall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='GAS_CALL', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='revert', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop execution and revert state changes, without consuming all provided gas\n and also has the ability to return a reason\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Name(id='output', ctx=Load())], + keywords=[])), + Raise( + exc=Name(id='Revert', ctx=Load())), + Pass()], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/instructions/system.v b/coq/ethereum/byzantium/vm/instructions/system.v new file mode 100644 index 0000000000..754ab4e94c --- /dev/null +++ b/coq/ethereum/byzantium/vm/instructions/system.v @@ -0,0 +1,666 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.byzantium.fork_types. +Require ethereum.byzantium.state. +Require ethereum.byzantium.utils.address. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.exceptions. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.memory. +Require ethereum.byzantium.vm.stack. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "create_message_gas" [[ + gas.max_message_call_gas ~(| + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) in + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_local ~(| "create_message_gas" |) + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (is_staticcall : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_SELF_DESTRUCT in + ]] in + (* TODO statement *) + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "refunded_accounts" [[ + M.get_field ~(| evm, "accounts_to_delete" |) in + ]] in + do* M.assign "parent_evm" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "parent_evm" |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + gas.GAS_CALL + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition staticcall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + gas.GAS_CALL + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "to" |), + M.get_local ~(| "to" |), + True, + True, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition revert (evm : Evm) : M unit := + (* + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "output" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/interpreter.ast b/coq/ethereum/byzantium/vm/interpreter.ast new file mode 100644 index 0000000000..aec20bf000 --- /dev/null +++ b/coq/ethereum/byzantium/vm/interpreter.ast @@ -0,0 +1,1123 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Iterable'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='increment_nonce'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidOpcode'), + alias(name='OutOfGasError'), + alias(name='Revert'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_CODE_SIZE', ctx=Store())], + value=Constant(value=24576)), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `touched_accounts`: Accounts that have been touched.\n 6. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='touched_accounts', + value=Name(id='touched_accounts', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.byzantium.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_CODE_SIZE', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.byzantium.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='touched_accounts', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='return_data', + value=Constant(value=b'')), + keyword( + arg='error', + value=Constant(value=None))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))]), + ExceptHandler( + type=Name(id='Revert', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/interpreter.v b/coq/ethereum/byzantium/vm/interpreter.v new file mode 100644 index 0000000000..20015c237b --- /dev/null +++ b/coq/ethereum/byzantium/vm/interpreter.v @@ -0,0 +1,169 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.byzantium.blocks. +Require ethereum.byzantium.fork_types. +Require ethereum.byzantium.state. +Require ethereum.byzantium.vm. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.precompiled_contracts.mapping. +Require ethereum.byzantium.vm.__init__. +Require ethereum.byzantium.vm.exceptions. +Require ethereum.byzantium.vm.instructions. +Require ethereum.byzantium.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.byzantium.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.byzantium.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/memory.ast b/coq/ethereum/byzantium/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/byzantium/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/memory.v b/coq/ethereum/byzantium/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/byzantium/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/__init__.ast b/coq/ethereum/byzantium/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..f93208d0c0 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,89 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS'), + Constant(value='MODEXP_ADDRESS'), + Constant(value='ALT_BN128_ADD_ADDRESS'), + Constant(value='ALT_BN128_MUL_ADDRESS'), + Constant(value='ALT_BN128_PAIRING_CHECK_ADDRESS'), + Constant(value='BLAKE2F_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[])), + Assign( + targets=[ + Name(id='MODEXP_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x05')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x06')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x07')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x08')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/__init__.v b/coq/ethereum/byzantium/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..24fa6cc8c6 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.byzantium.utils.hexadecimal. diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.ast b/coq/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.ast new file mode 100644 index 0000000000..dd403eba17 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.ast @@ -0,0 +1,913 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ALT_BN128 CONTRACTS\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ALT_BN128 precompiled contracts.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.alt_bn128', + names=[ + alias(name='ALT_BN128_CURVE_ORDER'), + alias(name='ALT_BN128_PRIME'), + alias(name='BNF'), + alias(name='BNF2'), + alias(name='BNF12'), + alias(name='BNP'), + alias(name='BNP2'), + alias(name='pairing')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=2), + FunctionDef( + name='alt_bn128_add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 addition precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=500)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load()), + Name(id='x1_value', ctx=Load()), + Name(id='y1_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='p1', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x1_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y1_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=BinOp( + left=Name(id='p0', ctx=Load()), + op=Add(), + right=Name(id='p1', ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 multiplication precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=40000)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='n', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='p0', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='n', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_pairing_check', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 pairing check precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=80000), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))), + op=Add(), + right=Constant(value=100000))], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=192)), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='values', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=Name(id='j', ctx=Load()))), + upper=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=BinOp( + left=Name(id='j', ctx=Load()), + op=Add(), + right=Constant(value=1))))), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='values', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=Call( + func=Name(id='BNP2', ctx=Load()), + args=[ + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=3), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=2), + ctx=Load())], + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=5), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=4), + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='OutOfGasError', ctx=Load()), + args=[], + keywords=[]))])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='p', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='q', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='p', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + Compare( + left=Name(id='q', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='result', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='pairing', ctx=Load()), + args=[ + Name(id='q', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[])))], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='result', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000000..12fc9193b1 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,226 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.alt_bn128. +Require ethereum.byzantium.vm. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.memory. +Require ethereum.byzantium.vm.exceptions. + +Definition alt_bn128_add (evm : Evm) : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 500 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "x1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x1_bytes" |) + |) + |) in + ]] in + do* M.assign "y1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y1_bytes" |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + (* TODO expression *) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_mul (evm : Evm) : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 40000 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "n" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + M.get_field ~(| M.get_local ~(| "p0" |), "mul_by" |) ~(| + M.get_local ~(| "n" |) + |) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_pairing_check (evm : Evm) : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + (* TODO expression *) + |) + |) ]] in + (* TODO statement *) + do* M.assign "result" [[ + M.get_field ~(| ethereum.crypto.alt_bn128.BNF12, "from_int" |) ~(| + 1 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/byzantium/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/byzantium/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..243767986f --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.byzantium.vm. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/identity.ast b/coq/ethereum/byzantium/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/identity.v b/coq/ethereum/byzantium/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..14e3685278 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.byzantium.vm. +Require ethereum.byzantium.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/mapping.ast b/coq/ethereum/byzantium/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..7d4dba4380 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,89 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ALT_BN128_ADD_ADDRESS'), + alias(name='ALT_BN128_MUL_ADDRESS'), + alias(name='ALT_BN128_PAIRING_CHECK_ADDRESS'), + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='MODEXP_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='alt_bn128', + names=[ + alias(name='alt_bn128_add'), + alias(name='alt_bn128_mul'), + alias(name='alt_bn128_pairing_check')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='modexp', + names=[ + alias(name='modexp')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load()), + Name(id='MODEXP_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load()), + Name(id='modexp', ctx=Load()), + Name(id='alt_bn128_add', ctx=Load()), + Name(id='alt_bn128_mul', ctx=Load()), + Name(id='alt_bn128_pairing_check', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/mapping.v b/coq/ethereum/byzantium/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..286ca189f8 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/mapping.v @@ -0,0 +1,24 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.byzantium.fork_types. +Require ethereum.byzantium.vm.precompiled_contracts.__init__. +Require ethereum.byzantium.vm.precompiled_contracts.alt_bn128. +Require ethereum.byzantium.vm.precompiled_contracts.ecrecover. +Require ethereum.byzantium.vm.precompiled_contracts.identity. +Require ethereum.byzantium.vm.precompiled_contracts.modexp. +Require ethereum.byzantium.vm.precompiled_contracts.ripemd160. +Require ethereum.byzantium.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/modexp.ast b/coq/ethereum/byzantium/vm/precompiled_contracts/modexp.ast new file mode 100644 index 0000000000..010c07fd00 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/modexp.ast @@ -0,0 +1,631 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `MODEXP` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + Assign( + targets=[ + Name(id='GQUADDIVISOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + FunctionDef( + name='modexp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and.\n `modulus`. The return value is the same length as the modulus.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='base_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_start', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Add(), + right=Name(id='base_length', ctx=Load()))), + Assign( + targets=[ + Name(id='exp_head', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Call( + func=Name(id='min', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='gas_cost', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load()), + Name(id='exp_length', ctx=Load()), + Name(id='exp_head', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='base_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='modulus_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Name(id='base_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_start', ctx=Store())], + value=BinOp( + left=Name(id='exp_start', ctx=Load()), + op=Add(), + right=Name(id='exp_length', ctx=Load()))), + Assign( + targets=[ + Name(id='modulus', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='modulus_start', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='modulus', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'\x00')], + keywords=[]), + op=Mult(), + right=Name(id='modulus_length', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exp', ctx=Load()), + Name(id='modulus', ctx=Load())], + keywords=[]), + attr='to_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[]), + Constant(value='big')], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='complexity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Estimate the complexity of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n Returns\n -------\n\n complexity : `Uint`\n Complexity of performing the operation.\n ')), + Assign( + targets=[ + Name(id='max_length', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load())], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='max_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[])]), + body=[ + Return( + value=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='max_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])]), + body=[ + Return( + value=BinOp( + left=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=4)], + keywords=[])), + op=Add(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Mult(), + right=Name(id='max_length', ctx=Load()))), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3072)], + keywords=[])))], + orelse=[ + Return( + value=BinOp( + left=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[])), + op=Add(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=480)], + keywords=[]), + op=Mult(), + right=Name(id='max_length', ctx=Load()))), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=199680)], + keywords=[])))])])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='iterations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the number of iterations required to perform a modular\n exponentiation.\n\n Parameters\n ----------\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n iterations : `Uint`\n Number of iterations.\n ')), + If( + test=Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='adjusted_exp_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Constant(value=0), + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + op=Sub(), + right=Constant(value=1))], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='adjusted_exp_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=8), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=32))), + op=Add(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + Constant(value=0), + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + op=Sub(), + right=Constant(value=1))], + keywords=[]))], + keywords=[]))]), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='adjusted_exp_length', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the gas cost of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n gas_cost : `Uint`\n Gas required for performing the operation.\n ')), + Assign( + targets=[ + Name(id='multiplication_complexity', ctx=Store())], + value=Call( + func=Name(id='complexity', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='iteration_count', ctx=Store())], + value=Call( + func=Name(id='iterations', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load()), + Name(id='exponent_head', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cost', ctx=Store())], + value=BinOp( + left=Name(id='multiplication_complexity', ctx=Load()), + op=Mult(), + right=Name(id='iteration_count', ctx=Load()))), + AugAssign( + target=Name(id='cost', ctx=Store()), + op=FloorDiv(), + value=Name(id='GQUADDIVISOR', ctx=Load())), + Return( + value=Name(id='cost', ctx=Load()))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/modexp.v b/coq/ethereum/byzantium/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000000..484d94ddfc --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/modexp.v @@ -0,0 +1,233 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.byzantium.vm. +Require ethereum.byzantium.vm.gas. +Require ethereum.byzantium.vm.memory. + +Definition modexp (evm : Evm) : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "base_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "modulus_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "exp_head" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "min" |) ~(| + ethereum_types.numeric.U256 ~(| + 32 + |), + M.get_local ~(| "exp_length" |) + |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) ~(| + M.get_local ~(| "base_length" |), + M.get_local ~(| "modulus_length" |), + M.get_local ~(| "exp_length" |), + M.get_local ~(| "exp_head" |) + |) + |) ]] in + (* TODO statement *) + do* M.assign "base" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + M.get_local ~(| "base_length" |) + |) + |) in + ]] in + do* M.assign "exp" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "exp_length" |) + |) + |) in + ]] in + do* M.assign "modulus_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "modulus" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "modulus_start" |), + M.get_local ~(| "modulus_length" |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := + (* + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + *) + do* M.assign "max_length" [[ + M.get_local ~(| "max" |) ~(| + ethereum_types.numeric.Uint ~(| + base_length + |), + ethereum_types.numeric.Uint ~(| + modulus_length + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition gas_cost (base_length : U256) (modulus_length : U256) (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + *) + do* M.assign "multiplication_complexity" [[ + M.get_local ~(| "complexity" |) ~(| + base_length, + modulus_length + |) in + ]] in + do* M.assign "iteration_count" [[ + M.get_local ~(| "iterations" |) ~(| + exponent_length, + exponent_head + |) in + ]] in + do* M.assign "cost" [[ + (* TODO expression *) in + ]] in + do* M.aug_assign [[ M.get_local ~(| "cost" |) ]] [[ + M.get_local ~(| "GQUADDIVISOR" |) + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/byzantium/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/byzantium/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/sha256.ast b/coq/ethereum/byzantium/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/precompiled_contracts/sha256.v b/coq/ethereum/byzantium/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/byzantium/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/runtime.ast b/coq/ethereum/byzantium/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/byzantium/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/runtime.v b/coq/ethereum/byzantium/vm/runtime.v new file mode 100644 index 0000000000..47bfec9776 --- /dev/null +++ b/coq/ethereum/byzantium/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.byzantium.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/byzantium/vm/stack.ast b/coq/ethereum/byzantium/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/byzantium/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/byzantium/vm/stack.v b/coq/ethereum/byzantium/vm/stack.v new file mode 100644 index 0000000000..3a9d0f579f --- /dev/null +++ b/coq/ethereum/byzantium/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.byzantium.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/__init__.ast b/coq/ethereum/cancun/__init__.ast new file mode 100644 index 0000000000..cedcfc26d3 --- /dev/null +++ b/coq/ethereum/cancun/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe Cancun fork introduces transient storage, exposes beacon chain roots,\nintroduces a new blob-carrying transaction type, adds a memory copying\ninstruction, limits self-destruct to only work for contracts created in the\nsame transaction, and adds an instruction to read the blob base fee.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByTimestamp')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByTimestamp', ctx=Load()), + args=[ + Constant(value=1710338135)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/__init__.v b/coq/ethereum/cancun/__init__.v new file mode 100644 index 0000000000..348a58a692 --- /dev/null +++ b/coq/ethereum/cancun/__init__.v @@ -0,0 +1,9 @@ +(* Generated *) +(* +The Cancun fork introduces transient storage, exposes beacon chain roots, +introduces a new blob-carrying transaction type, adds a memory copying +instruction, limits self-destruct to only work for contracts created in the +same transaction, and adds an instruction to read the blob base fee. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/cancun/blocks.ast b/coq/ethereum/cancun/blocks.ast new file mode 100644 index 0000000000..a05f4e7a06 --- /dev/null +++ b/coq/ethereum/cancun/blocks.ast @@ -0,0 +1,284 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='LegacyTransaction')], + level=1), + ClassDef( + name='Withdrawal', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Withdrawals that have been validated on the consensus layer.\n ')), + AnnAssign( + target=Name(id='index', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='validator_index', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='amount', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='prev_randao', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='withdrawals_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='blob_gas_used', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='excess_blob_gas', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_beacon_block_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='withdrawals', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Withdrawal', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='succeeded', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/blocks.v b/coq/ethereum/cancun/blocks.v new file mode 100644 index 0000000000..9bb75b168f --- /dev/null +++ b/coq/ethereum/cancun/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.cancun.fork_types. +Require ethereum.cancun.transactions. diff --git a/coq/ethereum/cancun/bloom.ast b/coq/ethereum/cancun/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/cancun/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/bloom.v b/coq/ethereum/cancun/bloom.v new file mode 100644 index 0000000000..722a5958a9 --- /dev/null +++ b/coq/ethereum/cancun/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.cancun.blocks. +Require ethereum.cancun.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/exceptions.ast b/coq/ethereum/cancun/exceptions.ast new file mode 100644 index 0000000000..a61ee25448 --- /dev/null +++ b/coq/ethereum/cancun/exceptions.ast @@ -0,0 +1,72 @@ +Module( + body=[ + Expr( + value=Constant(value='\nExceptions specific to this fork.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Final')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidTransaction')], + level=0), + ClassDef( + name='TransactionTypeError', + bases=[ + Name(id='InvalidTransaction', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Unknown [EIP-2718] transaction type byte.\n\n [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718\n ')), + AnnAssign( + target=Name(id='transaction_type', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n The type byte of the transaction that caused the error.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='transaction_type', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='unknown transaction type `'), + FormattedValue( + value=Name(id='transaction_type', ctx=Load()), + conversion=-1), + Constant(value='`')])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='transaction_type', + ctx=Store())], + value=Name(id='transaction_type', ctx=Load()))], + decorator_list=[])], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/exceptions.v b/coq/ethereum/cancun/exceptions.v new file mode 100644 index 0000000000..9a313f6d0e --- /dev/null +++ b/coq/ethereum/cancun/exceptions.v @@ -0,0 +1,7 @@ +(* Generated *) +(* +Exceptions specific to this fork. +*) + +Require typing. +Require ethereum.exceptions. diff --git a/coq/ethereum/cancun/fork.ast b/coq/ethereum/cancun/fork.ast new file mode 100644 index 0000000000..406c401cf5 --- /dev/null +++ b/coq/ethereum/cancun/fork.ast @@ -0,0 +1,3825 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt'), + alias(name='Withdrawal')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root'), + alias(name='VersionedHash')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='TransientStorage'), + alias(name='account_exists_and_is_empty'), + alias(name='destroy_account'), + alias(name='destroy_touched_empty_accounts'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='process_withdrawal'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_ACCESS_LIST_ADDRESS_COST'), + alias(name='TX_ACCESS_LIST_STORAGE_KEY_COST'), + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='AccessListTransaction'), + alias(name='BlobTransaction'), + alias(name='FeeMarketTransaction'), + alias(name='LegacyTransaction'), + alias(name='Transaction'), + alias(name='decode_transaction'), + alias(name='encode_transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=1), + ImportFrom( + module='vm.gas', + names=[ + alias(name='calculate_blob_gas_price'), + alias(name='calculate_data_fee'), + alias(name='calculate_excess_blob_gas'), + alias(name='calculate_total_blob_gas'), + alias(name='init_code_cost')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='MAX_CODE_SIZE'), + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='ELASTICITY_MULTIPLIER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='EMPTY_OMMER_HASH', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List(elts=[], ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='SYSTEM_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0xfffffffffffffffffffffffffffffffffffffffe')], + keywords=[])), + Assign( + targets=[ + Name(id='BEACON_ROOTS_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02')], + keywords=[])), + Assign( + targets=[ + Name(id='SYSTEM_TRANSACTION_GAS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30000000)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_BLOB_GAS_PER_BLOCK', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=786432)], + keywords=[])), + Assign( + targets=[ + Name(id='VERSIONED_HASH_VERSION_KZG', ctx=Store())], + value=Constant(value=b'\x01')), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Assign( + targets=[ + Name(id='excess_blob_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_excess_blob_gas', ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='excess_blob_gas', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='excess_blob_gas', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Tuple(elts=[], ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='prev_randao', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='chain', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='withdrawals', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_beacon_block_root', + ctx=Load()), + Name(id='excess_blob_gas', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='withdrawals_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='withdrawals_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='blob_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='blob_gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_base_fee_per_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the base fee per gas for the block.\n\n Parameters\n ----------\n block_gas_limit :\n Gas limit of the block for which the base fee is being calculated.\n parent_gas_limit :\n Gas limit of the parent block.\n parent_gas_used :\n Gas used in the parent block.\n parent_base_fee_per_gas :\n Base fee per gas of the parent block.\n\n Returns\n -------\n base_fee_per_gas : `Uint`\n Base fee per gas for the block.\n ')), + Assign( + targets=[ + Name(id='parent_gas_target', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='ELASTICITY_MULTIPLIER', ctx=Load()))), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Name(id='block_gas_limit', ctx=Load()), + Name(id='parent_gas_limit', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='parent_gas_used', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='parent_gas_target', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=Name(id='parent_base_fee_per_gas', ctx=Load()))], + orelse=[ + If( + test=Compare( + left=Name(id='parent_gas_used', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='parent_gas_target', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='gas_used_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_used', ctx=Load()), + op=Sub(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='parent_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Mult(), + right=Name(id='gas_used_delta', ctx=Load()))), + Assign( + targets=[ + Name(id='target_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='base_fee_per_gas_delta', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=Name(id='target_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Load())), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Add(), + right=Name(id='base_fee_per_gas_delta', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='gas_used_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_target', ctx=Load()), + op=Sub(), + right=Name(id='parent_gas_used', ctx=Load()))), + Assign( + targets=[ + Name(id='parent_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Mult(), + right=Name(id='gas_used_delta', ctx=Load()))), + Assign( + targets=[ + Name(id='target_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='base_fee_per_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='target_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Load()))), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Sub(), + right=Name(id='base_fee_per_gas_delta', ctx=Load())))])]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='expected_base_fee_per_gas', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_base_fee_per_gas', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='expected_base_fee_per_gas', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'\x00\x00\x00\x00\x00\x00\x00\x00')]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='EMPTY_OMMER_HASH', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='excess_blob_gas', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n state :\n Current state.\n tx :\n The transaction.\n gas_available :\n The gas remaining in the block.\n chain_id :\n The ID of the current chain.\n base_fee_per_gas :\n The block base fee.\n excess_blob_gas :\n The excess blob gas.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n effective_gas_price :\n The price to charge for gas when the transaction is executed.\n blob_versioned_hashes :\n The blob versioned hashes of the transaction.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='MAX_CODE_SIZE', ctx=Load()))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Tuple( + elts=[ + Name(id='FeeMarketTransaction', ctx=Load()), + Name(id='BlobTransaction', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='base_fee_per_gas', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='priority_fee_per_gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + op=Sub(), + right=Name(id='base_fee_per_gas', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='effective_gas_price', ctx=Store())], + value=BinOp( + left=Name(id='priority_fee_per_gas', ctx=Load()), + op=Add(), + right=Name(id='base_fee_per_gas', ctx=Load()))), + Assign( + targets=[ + Name(id='max_gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load())))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='base_fee_per_gas', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='effective_gas_price', ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())), + Assign( + targets=[ + Name(id='max_gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())))]), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='BlobTransaction', ctx=Load())], + keywords=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='blob_versioned_hashes', + ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + For( + target=Name(id='blob_versioned_hash', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='blob_versioned_hashes', + ctx=Load()), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='blob_versioned_hash', ctx=Load()), + slice=Slice( + lower=Constant(value=0), + upper=Constant(value=1)), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='VERSIONED_HASH_VERSION_KZG', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Name(id='blob_gas_price', ctx=Store())], + value=Call( + func=Name(id='calculate_blob_gas_price', ctx=Load()), + args=[ + Name(id='excess_blob_gas', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_blob_gas', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Name(id='blob_gas_price', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + AugAssign( + target=Name(id='max_gas_fee', ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='calculate_total_blob_gas', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_blob_gas', + ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='blob_versioned_hashes', ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='blob_versioned_hashes', + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='blob_versioned_hashes', ctx=Store())], + value=Tuple(elts=[], ctx=Load()))]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='max_gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='sender', ctx=Load()), + Name(id='effective_gas_price', ctx=Load()), + Name(id='blob_versioned_hashes', ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='VersionedHash', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='error', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n error :\n Error in the top level frame of the transaction, if any.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='succeeded', + value=Compare( + left=Name(id='error', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)])), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='receipt', ctx=Load())], + keywords=[])))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='receipt', ctx=Load())], + keywords=[])))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='BlobTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x03'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='receipt', ctx=Load())], + keywords=[])))], + orelse=[ + Return( + value=Name(id='receipt', ctx=Load()))])])])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Receipt', ctx=Load())], + ctx=Load()), + ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n withdrawals_root : `ethereum.fork_types.Root`\n Trie root of all the withdrawals in the block.\n blob_gas_used : `ethereum.base_types.Uint`\n Total blob gas used in the block.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='withdrawals_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='blob_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='prev_randao', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='withdrawals', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Withdrawal', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='parent_beacon_block_root', + annotation=Name(id='Root', ctx=Load())), + arg( + arg='excess_blob_gas', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n base_fee_per_gas :\n Base fee per gas of within the block.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n prev_randao :\n The previous randao from the beacon chain.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n chain_id :\n ID of the executing chain.\n withdrawals :\n Withdrawals to be processed in the current block.\n parent_beacon_block_root :\n The root of the beacon block from the parent block.\n excess_blob_gas :\n Excess blob gas calculated from the previous block.\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='blob_gas_used', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Receipt', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='withdrawals_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Withdrawal', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='beacon_block_roots_contract_code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='BEACON_ROOTS_ADDRESS', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='system_tx_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='SYSTEM_ADDRESS', ctx=Load())), + keyword( + arg='target', + value=Name(id='BEACON_ROOTS_ADDRESS', ctx=Load())), + keyword( + arg='gas', + value=Name(id='SYSTEM_TRANSACTION_GAS', ctx=Load())), + keyword( + arg='value', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='data', + value=Name(id='parent_beacon_block_root', ctx=Load())), + keyword( + arg='code', + value=Name(id='beacon_block_roots_contract_code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='BEACON_ROOTS_ADDRESS', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='BEACON_ROOTS_ADDRESS', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Constant(value=False)), + keyword( + arg='is_static', + value=Constant(value=False)), + keyword( + arg='accessed_addresses', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Constant(value=None))])), + Assign( + targets=[ + Name(id='system_tx_env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='SYSTEM_ADDRESS', ctx=Load())), + keyword( + arg='origin', + value=Name(id='SYSTEM_ADDRESS', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='base_fee_per_gas', + value=Name(id='base_fee_per_gas', ctx=Load())), + keyword( + arg='gas_price', + value=Name(id='base_fee_per_gas', ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='prev_randao', + value=Name(id='prev_randao', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='chain_id', + value=Name(id='chain_id', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load())), + keyword( + arg='excess_blob_gas', + value=Name(id='excess_blob_gas', ctx=Load())), + keyword( + arg='blob_versioned_hashes', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='transient_storage', + value=Call( + func=Name(id='TransientStorage', ctx=Load()), + args=[], + keywords=[]))])), + Assign( + targets=[ + Name(id='system_tx_output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='system_tx_message', ctx=Load()), + Name(id='system_tx_env', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_touched_empty_accounts', ctx=Load()), + args=[ + Attribute( + value=Name(id='system_tx_env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='system_tx_output', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Call( + func=Name(id='map', ctx=Load()), + args=[ + Name(id='decode_transaction', ctx=Load()), + Name(id='transactions', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Call( + func=Name(id='encode_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='sender_address', ctx=Store()), + Name(id='effective_gas_price', ctx=Store()), + Name(id='blob_versioned_hashes', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='tx', ctx=Load()), + Name(id='gas_available', ctx=Load()), + Name(id='chain_id', ctx=Load()), + Name(id='base_fee_per_gas', ctx=Load()), + Name(id='excess_blob_gas', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='base_fee_per_gas', + value=Name(id='base_fee_per_gas', ctx=Load())), + keyword( + arg='gas_price', + value=Name(id='effective_gas_price', ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='prev_randao', + value=Name(id='prev_randao', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='chain_id', + value=Name(id='chain_id', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load())), + keyword( + arg='excess_blob_gas', + value=Name(id='excess_blob_gas', ctx=Load())), + keyword( + arg='blob_versioned_hashes', + value=Name(id='blob_versioned_hashes', ctx=Load())), + keyword( + arg='transient_storage', + value=Call( + func=Name(id='TransientStorage', ctx=Load()), + args=[], + keywords=[]))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store()), + Name(id='error', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='error', ctx=Load()), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load())), + AugAssign( + target=Name(id='blob_gas_used', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='calculate_total_blob_gas', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='blob_gas_used', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_BLOB_GAS_PER_BLOCK', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='wd', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='withdrawals', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='withdrawals_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='wd', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='process_withdrawal', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='wd', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='wd', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='wd', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='withdrawals_trie', ctx=Load())], + keywords=[]), + Name(id='blob_gas_used', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='BlobTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='blob_gas_fee', ctx=Store())], + value=Call( + func=Name(id='calculate_data_fee', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='excess_blob_gas', + ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='blob_gas_fee', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Assign( + targets=[ + Name(id='effective_gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='effective_gas_fee', ctx=Load())), + op=Sub(), + right=Name(id='blob_gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='preaccessed_addresses', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='preaccessed_storage_keys', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Tuple( + elts=[ + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load()), + Name(id='BlobTransaction', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='address', ctx=Store()), + Name(id='keys', ctx=Store())], + ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='keys', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_storage_keys', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Name(id='address', ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[ + keyword( + arg='preaccessed_addresses', + value=Call( + func=Name(id='frozenset', ctx=Load()), + args=[ + Name(id='preaccessed_addresses', ctx=Load())], + keywords=[])), + keyword( + arg='preaccessed_storage_keys', + value=Call( + func=Name(id='frozenset', ctx=Load()), + args=[ + Name(id='preaccessed_storage_keys', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='priority_fee_per_gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Name(id='priority_fee_per_gas', ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + If( + test=Compare( + left=Name(id='coinbase_balance_after_mining_fee', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]))], + orelse=[])]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='destroy_touched_empty_accounts', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[])), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='error', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=BinOp( + left=Name(id='TX_CREATE_COST', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='init_code_cost', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])], + keywords=[])))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Assign( + targets=[ + Name(id='access_list_cost', ctx=Store())], + value=Constant(value=0)), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Tuple( + elts=[ + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load()), + Name(id='BlobTransaction', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='_address', ctx=Store()), + Name(id='keys', ctx=Store())], + ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + body=[ + AugAssign( + target=Name(id='access_list_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_ACCESS_LIST_ADDRESS_COST', ctx=Load())), + AugAssign( + target=Name(id='access_list_cost', ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='keys', ctx=Load())], + keywords=[]), + op=Mult(), + right=Name(id='TX_ACCESS_LIST_STORAGE_KEY_COST', ctx=Load())))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load())), + op=Add(), + right=Name(id='access_list_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=28)])]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash_pre155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='chain_id_x2', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=36)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[])), + op=Sub(), + right=Name(id='chain_id_x2', ctx=Load())), + Call( + func=Name(id='signing_hash_155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])], + keywords=[]))])], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='y_parity', + ctx=Load()), + Call( + func=Name(id='signing_hash_2930', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='y_parity', + ctx=Load()), + Call( + func=Name(id='signing_hash_1559', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='BlobTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='y_parity', + ctx=Load()), + Call( + func=Name(id='signing_hash_4844', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])])])]), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash_pre155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='LegacyTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a legacy (pre EIP 155) signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='LegacyTransaction', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 155 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n The id of the current chain.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='chain_id', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_2930', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='AccessListTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 2930 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load())], + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_1559', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='FeeMarketTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 1559 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load())], + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_4844', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='BlobTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP-4844 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x03'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_blob_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='blob_versioned_hashes', + ctx=Load())], + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/fork.v b/coq/ethereum/cancun/fork.v new file mode 100644 index 0000000000..22018ff221 --- /dev/null +++ b/coq/ethereum/cancun/fork.v @@ -0,0 +1,778 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.cancun.__init__. +Require ethereum.cancun.blocks. +Require ethereum.cancun.bloom. +Require ethereum.cancun.fork_types. +Require ethereum.cancun.state. +Require ethereum.cancun.transactions. +Require ethereum.cancun.trie. +Require ethereum.cancun.utils.hexadecimal. +Require ethereum.cancun.utils.message. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* M.assign "excess_blob_gas" [[ + vm.gas.calculate_excess_blob_gas ~(| + M.get_local ~(| "parent_header" |) + |) in + ]] in + (* TODO statement *) + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + (* TODO statement *) + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "base_fee_per_gas" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "prev_randao" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| chain, "chain_id" |), + M.get_field ~(| block, "withdrawals" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "parent_beacon_block_root" |), + M.get_local ~(| "excess_blob_gas" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_base_fee_per_gas (block_gas_limit : Uint) (parent_gas_limit : Uint) (parent_gas_used : Uint) (parent_base_fee_per_gas : Uint) : M Uint := + (* + 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. + *) + do* M.assign "parent_gas_target" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + (* TODO statement *) + do* M.assign "expected_base_fee_per_gas" [[ + M.get_local ~(| "calculate_base_fee_per_gas" |) ~(| + M.get_field ~(| header, "gas_limit" |), + M.get_field ~(| parent_header, "gas_limit" |), + M.get_field ~(| parent_header, "gas_used" |), + M.get_field ~(| parent_header, "base_fee_per_gas" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (state : State) (tx : Transaction) (gas_available : Uint) (chain_id : U64) (base_fee_per_gas : Uint) (excess_blob_gas : U64) : M (* TODO type *) := + (* + Check if the transaction is includable in the block. + + Parameters + ---------- + state : + Current state. + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + base_fee_per_gas : + The block base fee. + excess_blob_gas : + The excess blob gas. + + Returns + ------- + sender_address : + The sender of the transaction. + effective_gas_price : + The price to charge for gas when the transaction is executed. + blob_versioned_hashes : + The blob versioned hashes of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + state, + M.get_local ~(| "sender" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (error : (* TODO type *)) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (base_fee_per_gas : Uint) (block_gas_limit : Uint) (block_time : U256) (prev_randao : Bytes32) (transactions : (* TODO type *)) (chain_id : U64) (withdrawals : (* TODO type *)) (parent_beacon_block_root : Root) (excess_blob_gas : U64) : M ApplyBodyOutput := + (* + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + prev_randao : + The previous randao from the beacon chain. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + withdrawals : + Withdrawals to be processed in the current block. + parent_beacon_block_root : + The root of the beacon block from the parent block. + excess_blob_gas : + Excess blob gas calculated from the previous block. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "blob_gas_used" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "beacon_block_roots_contract_code" [[ + M.get_field ~(| state.get_account ~(| + state, + M.get_local ~(| "BEACON_ROOTS_ADDRESS" |) + |), "code" |) in + ]] in + do* M.assign "system_tx_message" [[ + vm.Message ~(| + + |) in + ]] in + do* M.assign "system_tx_env" [[ + M.get_field ~(| __init__.vm, "Environment" |) ~(| + + |) in + ]] in + do* M.assign "system_tx_output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "system_tx_message" |), + M.get_local ~(| "system_tx_env" |) + |) in + ]] in + do* [[ state.destroy_touched_empty_accounts ~(| + M.get_field ~(| M.get_local ~(| "system_tx_env" |), "state" |), + M.get_field ~(| M.get_local ~(| "system_tx_output" |), "touched_accounts" |) + |) ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "effective_gas_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "preaccessed_addresses" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "preaccessed_storage_keys" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "preaccessed_addresses" |), "add" |) ~(| + M.get_field ~(| env, "coinbase" |) + |) ]] in + (* TODO statement *) + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "priority_fee_per_gas" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ state.destroy_touched_empty_accounts ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| M.get_local ~(| "output" |), "touched_accounts" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "access_list_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_pre155 (tx : LegacyTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_155 (tx : LegacyTransaction) (chain_id : U64) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_2930 (tx : AccessListTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_1559 (tx : FeeMarketTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_4844 (tx : BlobTransaction) : M Hash32 := + (* + Compute the hash of a transaction used in a EIP-4844 signature. + + Parameters + ---------- + tx : + Transaction of interest. + + Returns + ------- + hash : `ethereum.crypto.hash.Hash32` + Hash of the transaction. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/fork_types.ast b/coq/ethereum/cancun/fork_types.ast new file mode 100644 index 0000000000..4f0e4e29ac --- /dev/null +++ b/coq/ethereum/cancun/fork_types.ast @@ -0,0 +1,150 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='VersionedHash', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/fork_types.v b/coq/ethereum/cancun/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/cancun/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/state.ast b/coq/ethereum/cancun/state.ast new file mode 100644 index 0000000000..f87ed536d5 --- /dev/null +++ b/coq/ethereum/cancun/state.ast @@ -0,0 +1,2062 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Iterable'), + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Withdrawal')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='created_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='set', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='TransientStorage', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between message calls\n within a transaction.\n ')), + AnnAssign( + target=Name(id='_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='transient_storage', + annotation=Name(id='TransientStorage', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n transient_storage : TransientStorage\n The transient storage of the transaction.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='transient_storage', + annotation=Name(id='TransientStorage', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n transient_storage : TransientStorage\n The transient storage of the transaction.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='transient_storage', + annotation=Name(id='TransientStorage', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n transient_storage : TransientStorage\n The transient storage of the transaction.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_tries', + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mark_account_created', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Mark an account as having been created in the current transaction.\n This information is used by `get_storage_original()` to handle an obscure\n edgecase.\n\n The marker is not removed even if the account creation reverts. Since the\n account cannot have had code prior to its creation and can't call\n `get_storage_original()`, this is harmless.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account that has been created.\n ")), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has zero nonce, empty code and zero balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_empty : `bool`\n True if if an account has zero nonce, empty code and zero balance,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_exists_and_is_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists and has zero nonce, empty code and zero\n balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n exists_and_is_empty : `bool`\n True if an account exists and has zero nonce, empty code and zero\n balance, False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='account', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_alive', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether is an account is both in the state and non empty.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_alive : `bool`\n True if the account is alive.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[ + Return( + value=UnaryOp( + op=Not(), + operand=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])])))])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_withdrawal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='wd', + annotation=Name(id='Withdrawal', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increase the balance of the withdrawing account.\n ')), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=BinOp( + left=Attribute( + value=Name(id='wd', ctx=Load()), + attr='amount', + ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=9))], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='wd', ctx=Load()), + attr='address', + ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage_original', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the original value in a storage slot i.e. the value before the current\n transaction began. This function reads the value from the snapshots taken\n before executing the transaction.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to read the value from.\n key:\n Key of the storage slot.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='_', ctx=Store()), + Name(id='original_trie', ctx=Store())], + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + Assign( + targets=[ + Name(id='original_account_trie', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='original_trie', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='original_account_trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='original_account_trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[]))]), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='original_value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='original_value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='get_transient_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='transient_storage', + annotation=Name(id='TransientStorage', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account from transient storage.\n Returns `U256(0)` if the storage key has not been set previously.\n Parameters\n ----------\n transient_storage: `TransientStorage`\n The transient storage\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_transient_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='transient_storage', + annotation=Name(id='TransientStorage', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n Parameters\n ----------\n transient_storage: `TransientStorage`\n The transient storage\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_touched_empty_accounts', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='touched_accounts', + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Destroy all touched accounts that are empty.\n Parameters\n ----------\n state: `State`\n The current state.\n touched_accounts: `Iterable[Address]`\n All the accounts that have been touched in the current transaction.\n ')), + For( + target=Name(id='address', ctx=Store()), + iter=Name(id='touched_accounts', ctx=Load()), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/state.v b/coq/ethereum/cancun/state.v new file mode 100644 index 0000000000..f1bb1f95bc --- /dev/null +++ b/coq/ethereum/cancun/state.v @@ -0,0 +1,694 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.cancun.blocks. +Require ethereum.cancun.fork_types. +Require ethereum.cancun.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) (transient_storage : TransientStorage) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + transient_storage : TransientStorage + The transient storage of the transaction. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| transient_storage, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) (transient_storage : TransientStorage) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + transient_storage : TransientStorage + The transient storage of the transaction. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| transient_storage, "_snapshots" |), "pop" |) ~(| + + |) ]] in + M.pure tt. + +Definition rollback_transaction (state : State) (transient_storage : TransientStorage) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + transient_storage : TransientStorage + The transient storage of the transaction. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition mark_account_created (state : State) (address : Address) : M unit := + (* + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| + address + |) ]] in + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_empty (state : State) (address : Address) : M bool := + (* + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition account_exists_and_is_empty (state : State) (address : Address) : M bool := + (* + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_alive (state : State) (address : Address) : M bool := + (* + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition process_withdrawal (state : State) (wd : Withdrawal) : M unit := + (* + Increase the balance of the withdrawing account. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + M.get_field ~(| wd, "address" |), + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition get_storage_original (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + *) + (* TODO statement *) + (* TODO assignment *) + do* M.assign "original_account_trie" [[ + M.get_field ~(| M.get_local ~(| "original_trie" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition get_transient_storage (transient_storage : TransientStorage) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account from transient storage. + Returns `U256(0)` if the storage key has not been set previously. + Parameters + ---------- + transient_storage: `TransientStorage` + The transient storage + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| transient_storage, "_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_transient_storage (transient_storage : TransientStorage) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + Parameters + ---------- + transient_storage: `TransientStorage` + The transient storage + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| transient_storage, "_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition destroy_touched_empty_accounts (state : State) (touched_accounts : (* TODO type *)) : M unit := + (* + Destroy all touched accounts that are empty. + Parameters + ---------- + state: `State` + The current state. + touched_accounts: `Iterable[Address]` + All the accounts that have been touched in the current transaction. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/transactions.ast b/coq/ethereum/cancun/transactions.ast new file mode 100644 index 0000000000..1ba3903365 --- /dev/null +++ b/coq/ethereum/cancun/transactions.ast @@ -0,0 +1,635 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='TransactionTypeError')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='VersionedHash')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + Assign( + targets=[ + Name(id='TX_ACCESS_LIST_ADDRESS_COST', ctx=Store())], + value=Constant(value=2400)), + Assign( + targets=[ + Name(id='TX_ACCESS_LIST_STORAGE_KEY_COST', ctx=Store())], + value=Constant(value=1900)), + ClassDef( + name='LegacyTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='AccessListTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The transaction type added in EIP-2930 to support access lists.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='access_list', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y_parity', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='FeeMarketTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The transaction type added in EIP-1559.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_priority_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='access_list', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y_parity', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BlobTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The transaction type added in EIP-4844.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_priority_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='access_list', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_fee_per_blob_gas', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='blob_versioned_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='VersionedHash', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y_parity', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='Transaction', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load()), + Name(id='BlobTransaction', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Encode a transaction. Needed because non-legacy transactions aren't RLP.\n ")), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='tx', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='BlobTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x03'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])))], + orelse=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Unable to encode transaction of type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + conversion=-1)])], + keywords=[]))])])])])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='decode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Decode a transaction. Needed because non-legacy transactions aren't RLP.\n ")), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Name(id='AccessListTransaction', ctx=Load()), + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=2)]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Name(id='FeeMarketTransaction', ctx=Load()), + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=3)]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Name(id='BlobTransaction', ctx=Load()), + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())], + keywords=[]))], + orelse=[ + Raise( + exc=Call( + func=Name(id='TransactionTypeError', ctx=Load()), + args=[ + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]))])])])], + orelse=[ + Return( + value=Name(id='tx', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Transaction', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/transactions.v b/coq/ethereum/cancun/transactions.v new file mode 100644 index 0000000000..530970c094 --- /dev/null +++ b/coq/ethereum/cancun/transactions.v @@ -0,0 +1,29 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.cancun.exceptions. +Require ethereum.cancun.fork_types. + +Definition encode_transaction (tx : Transaction) : M (* TODO type *) := + (* + Encode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + M.pure tt. + +Definition decode_transaction (tx : (* TODO type *)) : M Transaction := + (* + Decode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/trie.ast b/coq/ethereum/cancun/trie.ast new file mode 100644 index 0000000000..998cc53d11 --- /dev/null +++ b/coq/ethereum/cancun/trie.ast @@ -0,0 +1,1646 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.shanghai', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt'), + alias(name='Withdrawal')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='LegacyTransaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Name(id='Withdrawal', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Receipt', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Withdrawal', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.Extended`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Withdrawal', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/trie.v b/coq/ethereum/cancun/trie.v new file mode 100644 index 0000000000..3b45315972 --- /dev/null +++ b/coq/ethereum/cancun/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.Extended` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/utils/__init__.ast b/coq/ethereum/cancun/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/cancun/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/utils/__init__.v b/coq/ethereum/cancun/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/cancun/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/cancun/utils/address.ast b/coq/ethereum/cancun/utils/address.ast new file mode 100644 index 0000000000..a94a759c63 --- /dev/null +++ b/coq/ethereum/cancun/utils/address.ast @@ -0,0 +1,216 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this cancun version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_create2_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='salt', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='call_data', + annotation=Name(id='bytearray', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created, which is\n based on the sender address, salt and the call data as well.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n salt :\n Address generation salt.\n call_data :\n The code of the new account which is to be created.\n\n Returns\n -------\n address: `ethereum.cancun.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='preimage', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Constant(value=b'\xff'), + op=Add(), + right=Name(id='address', ctx=Load())), + op=Add(), + right=Name(id='salt', ctx=Load())), + op=Add(), + right=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='call_data', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/utils/address.v b/coq/ethereum/cancun/utils/address.v new file mode 100644 index 0000000000..f4f3877242 --- /dev/null +++ b/coq/ethereum/cancun/utils/address.v @@ -0,0 +1,115 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this cancun version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.cancun.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition compute_create2_contract_address (address : Address) (salt : Bytes32) (call_data : bytearray) : M Address := + (* + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.cancun.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "preimage" [[ + (* TODO expression *) in + ]] in + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "preimage" |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/utils/hexadecimal.ast b/coq/ethereum/cancun/utils/hexadecimal.ast new file mode 100644 index 0000000000..2f53dc38ab --- /dev/null +++ b/coq/ethereum/cancun/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to\nCancun types.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/utils/hexadecimal.v b/coq/ethereum/cancun/utils/hexadecimal.v new file mode 100644 index 0000000000..ac8639bbe3 --- /dev/null +++ b/coq/ethereum/cancun/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Cancun types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.cancun.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/utils/message.ast b/coq/ethereum/cancun/utils/message.ast new file mode 100644 index 0000000000..1bcbe39833 --- /dev/null +++ b/coq/ethereum/cancun/utils/message.ast @@ -0,0 +1,335 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this cancun version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='FrozenSet'), + alias(name='Optional'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_static', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='preaccessed_addresses', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='preaccessed_storage_keys', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True), + Constant(value=False), + Call( + func=Name(id='frozenset', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='frozenset', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n is_static:\n if True then it prevents all state-changing operations from being\n executed.\n preaccessed_addresses:\n Addresses that should be marked as accessed prior to the message call\n preaccessed_storage_keys:\n Storage keys that should be marked as accessed prior to the message\n call\n\n Returns\n -------\n message: `ethereum.cancun.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Assign( + targets=[ + Name(id='accessed_addresses', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='current_target', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='caller', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Name(id='preaccessed_addresses', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=Name(id='is_static', ctx=Load())), + keyword( + arg='accessed_addresses', + value=Name(id='accessed_addresses', ctx=Load())), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='preaccessed_storage_keys', ctx=Load())], + keywords=[])), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/utils/message.v b/coq/ethereum/cancun/utils/message.v new file mode 100644 index 0000000000..f674f71474 --- /dev/null +++ b/coq/ethereum/cancun/utils/message.v @@ -0,0 +1,85 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this cancun version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.cancun.fork_types. +Require ethereum.cancun.state. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.precompiled_contracts.mapping. +Require ethereum.cancun.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) (is_static : bool) (preaccessed_addresses : (* TODO type *)) (preaccessed_storage_keys : (* TODO type *)) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.cancun.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + do* M.assign "accessed_addresses" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "add" |) ~(| + M.get_local ~(| "current_target" |) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "add" |) ~(| + caller + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS, "keys" |) ~(| + + |) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + preaccessed_addresses + |) ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/vm/__init__.ast b/coq/ethereum/cancun/vm/__init__.ast new file mode 100644 index 0000000000..7f5c7f4b15 --- /dev/null +++ b/coq/ethereum/cancun/vm/__init__.ast @@ -0,0 +1,612 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='VersionedHash')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='TransientStorage'), + alias(name='account_exists_and_is_empty')], + level=2), + ImportFrom( + module='precompiled_contracts', + names=[ + alias(name='RIPEMD160_ADDRESS')], + level=1), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='prev_randao', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='excess_blob_gas', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='blob_versioned_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='VersionedHash', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transient_storage', ctx=Store()), + annotation=Name(id='TransientStorage', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='is_static', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_addresses', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_storage_keys', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='return_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_addresses', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_storage_keys', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + If( + test=Compare( + left=Name(id='RIPEMD160_ADDRESS', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/__init__.v b/coq/ethereum/cancun/vm/__init__.v new file mode 100644 index 0000000000..76bc5c2d6a --- /dev/null +++ b/coq/ethereum/cancun/vm/__init__.v @@ -0,0 +1,78 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.cancun.blocks. +Require ethereum.cancun.fork_types. +Require ethereum.cancun.state. +Require ethereum.cancun.vm.precompiled_contracts. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "touched_accounts" |), "update" |) ~(| + M.get_field ~(| child_evm, "touched_accounts" |) + |) ]] in + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| child_evm, "accessed_addresses" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_storage_keys" |), "update" |) ~(| + M.get_field ~(| child_evm, "accessed_storage_keys" |) + |) ]] in + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + (* TODO statement *) + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/cancun/vm/exceptions.ast b/coq/ethereum/cancun/vm/exceptions.ast new file mode 100644 index 0000000000..1665dd8581 --- /dev/null +++ b/coq/ethereum/cancun/vm/exceptions.ast @@ -0,0 +1,185 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='Revert', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised by the `REVERT` opcode.\n\n Unlike other EVM exceptions this does not result in the consumption of all\n gas.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='WriteInStaticContext', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt is made to modify the state while operating inside\n of a STATICCALL context.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfBoundsRead', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt was made to read data beyond the\n boundaries of the buffer.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidParameter', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when invalid parameters are passed.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidContractPrefix', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract code starts with 0xEF.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='KZGProofError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Raised when the point evaluation precompile can't verify a proof.\n ")), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/exceptions.v b/coq/ethereum/cancun/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/cancun/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/cancun/vm/gas.ast b/coq/ethereum/cancun/vm/gas.ast new file mode 100644 index 0000000000..f41eff4bb8 --- /dev/null +++ b/coq/ethereum/cancun/vm/gas.ast @@ -0,0 +1,1106 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32'), + alias(name='taylor_exponential')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Header')], + level=2), + ImportFrom( + module='transactions', + names=[ + alias(name='BlobTransaction'), + alias(name='Transaction')], + level=2), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=4800)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RETURN_DATA_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_FAST_STEP', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLAKE2_PER_ROUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COLD_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2100)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_WARM_ACCESS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=100)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_INIT_CODE_WORD_COST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOBHASH_OPCODE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_POINT_EVALUATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50000)], + keywords=[])), + Assign( + targets=[ + Name(id='TARGET_BLOB_GAS_PER_BLOCK', ctx=Store())], + value=Call( + func=Name(id='U64', ctx=Load()), + args=[ + Constant(value=393216)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_PER_BLOB', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=17))], + keywords=[])), + Assign( + targets=[ + Name(id='MIN_BLOB_GASPRICE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='BLOB_GASPRICE_UPDATE_FRACTION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3338477)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_left', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='memory_cost', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='extra_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='call_stipend', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Expr( + value=Constant(value='\n Calculates the MessageCallGas (cost and stipend) for\n executing call Opcodes.\n\n Parameters\n ----------\n value:\n The amount of `ETH` that needs to be transferred.\n gas :\n The amount of gas provided to the message-call.\n gas_left :\n The amount of gas left in the current frame.\n memory_cost :\n The amount needed to extend the memory in the current frame.\n extra_gas :\n The amount of gas needed for transferring value + creating a new\n account inside a message call.\n call_stipend :\n The amount of stipend provided to a message call to execute code while\n transferring value(ETH).\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='call_stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='call_stipend', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='extra_gas', ctx=Load()), + op=Add(), + right=Name(id='memory_cost', ctx=Load()))]), + body=[ + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='gas', ctx=Load()), + Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='gas_left', ctx=Load()), + op=Sub(), + right=Name(id='memory_cost', ctx=Load())), + op=Sub(), + right=Name(id='extra_gas', ctx=Load()))], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load())), + FunctionDef( + name='max_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the maximum gas that is allowed for making a message call\n\n Parameters\n ----------\n gas :\n The amount of gas provided to the message-call.\n\n Returns\n -------\n max_allowed_message_call_gas: `ethereum.base_types.Uint`\n The maximum gas allowed for making the message-call.\n ')), + Return( + value=BinOp( + left=Name(id='gas', ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='gas', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]))))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='init_code_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='init_code_length', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas to be charged for the init code in CREAT*\n opcodes as well as create transactions.\n\n Parameters\n ----------\n init_code_length :\n The length of the init code provided to the opcode\n or a create transaction\n\n Returns\n -------\n init_code_gas: `ethereum.base_types.Uint`\n The gas to be charged for the init code.\n ')), + Return( + value=BinOp( + left=BinOp( + left=Name(id='GAS_INIT_CODE_WORD_COST', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='init_code_length', ctx=Load())], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_excess_blob_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculated the excess blob gas for the current block based\n on the gas used in the parent block.\n\n Parameters\n ----------\n parent_header :\n The parent block of the current block.\n\n Returns\n -------\n excess_blob_gas: `ethereum.base_types.U64`\n The excess blob gas for the current block.\n ')), + Assign( + targets=[ + Name(id='excess_blob_gas', ctx=Store())], + value=Call( + func=Name(id='U64', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='blob_gas_used', ctx=Store())], + value=Call( + func=Name(id='U64', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load()), + Name(id='Header', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='excess_blob_gas', ctx=Store())], + value=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='excess_blob_gas', + ctx=Load())), + Assign( + targets=[ + Name(id='blob_gas_used', ctx=Store())], + value=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='blob_gas_used', + ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='parent_blob_gas', ctx=Store())], + value=BinOp( + left=Name(id='excess_blob_gas', ctx=Load()), + op=Add(), + right=Name(id='blob_gas_used', ctx=Load()))), + If( + test=Compare( + left=Name(id='parent_blob_gas', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='TARGET_BLOB_GAS_PER_BLOCK', ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='U64', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Return( + value=BinOp( + left=Name(id='parent_blob_gas', ctx=Load()), + op=Sub(), + right=Name(id='TARGET_BLOB_GAS_PER_BLOCK', ctx=Load())))])], + decorator_list=[], + returns=Name(id='U64', ctx=Load())), + FunctionDef( + name='calculate_total_blob_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the total blob gas for a transaction.\n\n Parameters\n ----------\n tx :\n The transaction for which the blob gas is to be calculated.\n\n Returns\n -------\n total_blob_gas: `ethereum.base_types.Uint`\n The total blob gas for the transaction.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='BlobTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Name(id='GAS_PER_BLOB', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='blob_versioned_hashes', + ctx=Load())], + keywords=[])], + keywords=[])))], + orelse=[ + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_blob_gas_price', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='excess_blob_gas', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the blob gasprice for a block.\n\n Parameters\n ----------\n excess_blob_gas :\n The excess blob gas for the block.\n\n Returns\n -------\n blob_gasprice: `Uint`\n The blob gasprice.\n ')), + Return( + value=Call( + func=Name(id='taylor_exponential', ctx=Load()), + args=[ + Name(id='MIN_BLOB_GASPRICE', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='excess_blob_gas', ctx=Load())], + keywords=[]), + Name(id='BLOB_GASPRICE_UPDATE_FRACTION', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_data_fee', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='excess_blob_gas', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the blob data fee for a transaction.\n\n Parameters\n ----------\n excess_blob_gas :\n The excess_blob_gas for the execution.\n tx :\n The transaction for which the blob data fee is to be calculated.\n\n Returns\n -------\n data_fee: `Uint`\n The blob data fee.\n ')), + Return( + value=BinOp( + left=Call( + func=Name(id='calculate_total_blob_gas', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='calculate_blob_gas_price', ctx=Load()), + args=[ + Name(id='excess_blob_gas', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/gas.v b/coq/ethereum/cancun/vm/gas.v new file mode 100644 index 0000000000..6b09f8bc61 --- /dev/null +++ b/coq/ethereum/cancun/vm/gas.v @@ -0,0 +1,277 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.cancun.blocks. +Require ethereum.cancun.transactions. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (value : U256) (gas : Uint) (gas_left : Uint) (memory_cost : Uint) (extra_gas : Uint) (call_stipend : Uint) : M MessageCallGas := + (* + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "gas" [[ + M.get_local ~(| "min" |) ~(| + gas, + M.get_local ~(| "max_message_call_gas" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition max_message_call_gas (gas : Uint) : M Uint := + (* + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + *) + (* TODO statement *) + M.pure tt. + +Definition init_code_cost (init_code_length : Uint) : M Uint := + (* + Calculates the gas to be charged for the init code in CREAT* + opcodes as well as create transactions. + + Parameters + ---------- + init_code_length : + The length of the init code provided to the opcode + or a create transaction + + Returns + ------- + init_code_gas: `ethereum.base_types.Uint` + The gas to be charged for the init code. + *) + (* TODO statement *) + M.pure tt. + +Definition calculate_excess_blob_gas (parent_header : Header) : M U64 := + (* + Calculated the excess blob gas for the current block based + on the gas used in the parent block. + + Parameters + ---------- + parent_header : + The parent block of the current block. + + Returns + ------- + excess_blob_gas: `ethereum.base_types.U64` + The excess blob gas for the current block. + *) + do* M.assign "excess_blob_gas" [[ + ethereum_types.numeric.U64 ~(| + 0 + |) in + ]] in + do* M.assign "blob_gas_used" [[ + ethereum_types.numeric.U64 ~(| + 0 + |) in + ]] in + (* TODO statement *) + do* M.assign "parent_blob_gas" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_total_blob_gas (tx : Transaction) : M Uint := + (* + Calculate the total blob gas for a transaction. + + Parameters + ---------- + tx : + The transaction for which the blob gas is to be calculated. + + Returns + ------- + total_blob_gas: `ethereum.base_types.Uint` + The total blob gas for the transaction. + *) + (* TODO statement *) + M.pure tt. + +Definition calculate_blob_gas_price (excess_blob_gas : U64) : M Uint := + (* + Calculate the blob gasprice for a block. + + Parameters + ---------- + excess_blob_gas : + The excess blob gas for the block. + + Returns + ------- + blob_gasprice: `Uint` + The blob gasprice. + *) + (* TODO statement *) + M.pure tt. + +Definition calculate_data_fee (excess_blob_gas : U64) (tx : Transaction) : M Uint := + (* + Calculate the blob data fee for a transaction. + + Parameters + ---------- + excess_blob_gas : + The excess_blob_gas for the execution. + tx : + The transaction for which the blob data fee is to be calculated. + + Returns + ------- + data_fee: `Uint` + The blob data fee. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/vm/instructions/__init__.ast b/coq/ethereum/cancun/vm/instructions/__init__.ast new file mode 100644 index 0000000000..b5ae8c5daf --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/__init__.ast @@ -0,0 +1,1864 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='SHL', ctx=Store())], + value=Constant(value=27)), + Assign( + targets=[ + Name(id='SHR', ctx=Store())], + value=Constant(value=28)), + Assign( + targets=[ + Name(id='SAR', ctx=Store())], + value=Constant(value=29)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='RETURNDATASIZE', ctx=Store())], + value=Constant(value=61)), + Assign( + targets=[ + Name(id='RETURNDATACOPY', ctx=Store())], + value=Constant(value=62)), + Assign( + targets=[ + Name(id='EXTCODEHASH', ctx=Store())], + value=Constant(value=63)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='PREVRANDAO', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='CHAINID', ctx=Store())], + value=Constant(value=70)), + Assign( + targets=[ + Name(id='SELFBALANCE', ctx=Store())], + value=Constant(value=71)), + Assign( + targets=[ + Name(id='BASEFEE', ctx=Store())], + value=Constant(value=72)), + Assign( + targets=[ + Name(id='BLOBHASH', ctx=Store())], + value=Constant(value=73)), + Assign( + targets=[ + Name(id='BLOBBASEFEE', ctx=Store())], + value=Constant(value=74)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='TLOAD', ctx=Store())], + value=Constant(value=92)), + Assign( + targets=[ + Name(id='TSTORE', ctx=Store())], + value=Constant(value=93)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH0', ctx=Store())], + value=Constant(value=95)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='MCOPY', ctx=Store())], + value=Constant(value=94)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='CREATE2', ctx=Store())], + value=Constant(value=245)), + Assign( + targets=[ + Name(id='STATICCALL', ctx=Store())], + value=Constant(value=250)), + Assign( + targets=[ + Name(id='REVERT', ctx=Store())], + value=Constant(value=253)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SAR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PREVRANDAO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CHAINID', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MCOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODEHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFBALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BASEFEE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOBHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOBBASEFEE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STATICCALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='REVERT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE2', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shl', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shr', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_sar', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='prev_randao', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mcopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodehash', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='self_balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='base_fee', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='blob_hash', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='blob_base_fee', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='tload', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='tstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push0', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='staticcall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='revert', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create2', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/instructions/__init__.v b/coq/ethereum/cancun/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/cancun/vm/instructions/arithmetic.ast b/coq/ethereum/cancun/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/instructions/arithmetic.v b/coq/ethereum/cancun/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..221e17dee5 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/cancun/vm/instructions/bitwise.ast b/coq/ethereum/cancun/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..b72397f0ec --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/bitwise.ast @@ -0,0 +1,751 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shl', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift left (SHL) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='value', ctx=Load()), + op=LShift(), + right=Name(id='shift', ctx=Load())), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]))], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shr', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift right (SHR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_sar', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Arithmetic shift right (SAR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='signed_value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=256)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + BinOp( + left=Name(id='signed_value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load()))], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='signed_value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load()))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/instructions/bitwise.v b/coq/ethereum/cancun/vm/instructions/bitwise.v new file mode 100644 index 0000000000..4a3d09cf84 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/bitwise.v @@ -0,0 +1,309 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shl (evm : Evm) : M unit := + (* + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shr (evm : Evm) : M unit := + (* + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_sar (evm : Evm) : M unit := + (* + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + M.get_local ~(| "int" |) ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "signed_value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/cancun/vm/instructions/block.ast b/coq/ethereum/cancun/vm/instructions/block.ast new file mode 100644 index 0000000000..ca57ef8a6a --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/block.ast @@ -0,0 +1,495 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.cancun.vm.exceptions.StackUnderflowError`\n If `len(stack)` is less than `1`.\n :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `20`.\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='prev_randao', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the `prev_randao` value onto the stack.\n\n The `prev_randao` value is the random output of the beacon chain's\n randomness oracle for the previous block.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='prev_randao', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='chain_id', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the chain id onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/instructions/block.v b/coq/ethereum/cancun/vm/instructions/block.v new file mode 100644 index 0000000000..20caf34a0d --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/block.v @@ -0,0 +1,283 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.cancun.vm.exceptions.StackUnderflowError` + If `len(stack)` is less than `1`. + :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `20`. + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition prev_randao (evm : Evm) : M unit := + (* + Push the `prev_randao` value onto the stack. + + The `prev_randao` value is the random output of the beacon chain's + randomness oracle for the previous block. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "prev_randao" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition chain_id (evm : Evm) : M unit := + (* + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.cancun.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.cancun.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/cancun/vm/instructions/comparison.ast b/coq/ethereum/cancun/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/instructions/comparison.v b/coq/ethereum/cancun/vm/instructions/comparison.v new file mode 100644 index 0000000000..e04e5c9ca2 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/cancun/vm/instructions/control_flow.ast b/coq/ethereum/cancun/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/instructions/control_flow.v b/coq/ethereum/cancun/vm/instructions/control_flow.v new file mode 100644 index 0000000000..958c0bd396 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.exceptions. +Require ethereum.cancun.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/cancun/vm/instructions/environment.ast b/coq/ethereum/cancun/vm/instructions/environment.ast new file mode 100644 index 0000000000..f0ddc073d0 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/environment.ast @@ -0,0 +1,2007 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfBoundsRead')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOBHASH_OPCODE'), + alias(name='GAS_COLD_ACCOUNT_ACCESS'), + alias(name='GAS_COPY'), + alias(name='GAS_FAST_STEP'), + alias(name='GAS_RETURN_DATA_COPY'), + alias(name='GAS_VERY_LOW'), + alias(name='GAS_WARM_ACCESS'), + alias(name='calculate_blob_gas_price'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_WARM_ACCESS', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the size of the return data buffer onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copies data from the return data buffer code to memory\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='return_data_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_RETURN_DATA_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='return_data_start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfBoundsRead', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load()), + slice=Slice( + lower=Name(id='return_data_start_position', ctx=Load()), + upper=BinOp( + left=Name(id='return_data_start_position', ctx=Load()), + op=Add(), + right=Name(id='size', ctx=Load()))), + ctx=Load())), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodehash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns the keccak256 hash of a contract’s bytecode\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='EMPTY_ACCOUNT', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codehash', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='self_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the current address to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_FAST_STEP', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='base_fee', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the base fee of the current block on to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='blob_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the versioned hash at a particular index on to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOBHASH_OPCODE', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='index', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='blob_versioned_hashes', + ctx=Load())], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='blob_hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='blob_versioned_hashes', + ctx=Load()), + slice=Name(id='index', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='blob_hash', ctx=Store())], + value=Call( + func=Name(id='Bytes32', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=32))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='blob_hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='blob_base_fee', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the blob base fee on to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='blob_base_fee', ctx=Store())], + value=Call( + func=Name(id='calculate_blob_gas_price', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='excess_blob_gas', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='blob_base_fee', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/instructions/environment.v b/coq/ethereum/cancun/vm/instructions/environment.v new file mode 100644 index 0000000000..cfdf2a756d --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/environment.v @@ -0,0 +1,795 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.cancun.fork_types. +Require ethereum.cancun.state. +Require ethereum.cancun.utils.address. +Require ethereum.cancun.vm.memory. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.exceptions. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatasize (evm : Evm) : M unit := + (* + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatacopy (evm : Evm) : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "return_data_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + (* TODO expression *) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodehash (evm : Evm) : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "account" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codehash" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition self_balance (evm : Evm) : M unit := + (* + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_FAST_STEP + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition base_fee (evm : Evm) : M unit := + (* + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "base_fee_per_gas" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition blob_hash (evm : Evm) : M unit := + (* + Pushes the versioned hash at a particular index on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOBHASH_OPCODE + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "blob_hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition blob_base_fee (evm : Evm) : M unit := + (* + Pushes the blob base fee on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* M.assign "blob_base_fee" [[ + gas.calculate_blob_gas_price ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "excess_blob_gas" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "blob_base_fee" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/cancun/vm/instructions/keccak.ast b/coq/ethereum/cancun/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/instructions/keccak.v b/coq/ethereum/cancun/vm/instructions/keccak.v new file mode 100644 index 0000000000..c0f33ddc8d --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.memory. +Require ethereum.cancun.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/cancun/vm/instructions/log.ast b/coq/ethereum/cancun/vm/instructions/log.ast new file mode 100644 index 0000000000..0ded0e04ba --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/log.ast @@ -0,0 +1,323 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/instructions/log.v b/coq/ethereum/cancun/vm/instructions/log.v new file mode 100644 index 0000000000..d1439aa2d8 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/log.v @@ -0,0 +1,79 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.cancun.blocks. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.exceptions. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.memory. +Require ethereum.cancun.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO statement *) + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/cancun/vm/instructions/memory.ast b/coq/ethereum/cancun/vm/instructions/memory.ast new file mode 100644 index 0000000000..8c10178d17 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/memory.ast @@ -0,0 +1,632 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_COPY'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mcopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy the bytes in memory from one location to another.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='source', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='length', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='length', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='source', ctx=Load()), + Name(id='length', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='destination', ctx=Load()), + Name(id='length', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='source', ctx=Load()), + Name(id='length', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='destination', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/instructions/memory.v b/coq/ethereum/cancun/vm/instructions/memory.v new file mode 100644 index 0000000000..e423105fad --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/memory.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.memory. +Require ethereum.cancun.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mcopy (evm : Evm) : M unit := + (* + Copy the bytes in memory from one location to another. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "destination" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "source" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "length" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "source" |), + M.get_local ~(| "length" |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "destination" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/cancun/vm/instructions/stack.ast b/coq/ethereum/cancun/vm/instructions/stack.ast new file mode 100644 index 0000000000..79c3c451b2 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/stack.ast @@ -0,0 +1,1110 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack. Push zero if num_bytes is zero.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack. Push zero if num_bytes is zero.\n\n ')), + Pass(), + If( + test=Compare( + left=Name(id='num_bytes', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/instructions/stack.v b/coq/ethereum/cancun/vm/instructions/stack.v new file mode 100644 index 0000000000..892e22ae4a --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/stack.v @@ -0,0 +1,150 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.exceptions. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. Push zero if num_bytes is zero. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. Push zero if num_bytes is zero. + + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/cancun/vm/instructions/storage.ast b/coq/ethereum/cancun/vm/instructions/storage.ast new file mode 100644 index 0000000000..a3e90e6e70 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/storage.ast @@ -0,0 +1,731 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='get_storage_original'), + alias(name='get_transient_storage'), + alias(name='set_storage'), + alias(name='set_transient_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_STIPEND'), + alias(name='GAS_COLD_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='GAS_WARM_ACCESS'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_SLOAD', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='get_storage_original', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + If( + test=Compare( + left=Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_COLD_SLOAD', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='current_value', ctx=Load())]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())])]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_COLD_SLOAD', ctx=Load())))])], + orelse=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))]), + If( + test=Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='GAS_STORAGE_SET', ctx=Load()), + op=Sub(), + right=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + keywords=[]))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_COLD_SLOAD', ctx=Load())), + op=Sub(), + right=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + keywords=[]))])], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='tload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n transient storage of the current account.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_transient_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='transient_storage', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='tstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's transient storage.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='set_transient_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='transient_storage', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/instructions/storage.v b/coq/ethereum/cancun/vm/instructions/storage.v new file mode 100644 index 0000000000..10d072cd60 --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/storage.v @@ -0,0 +1,197 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.cancun.state. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.exceptions. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "original_value" [[ + state.get_storage_original ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "gas_cost" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition tload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + transient storage of the current account. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_WARM_ACCESS + |) ]] in + do* M.assign "value" [[ + state.get_transient_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "transient_storage" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition tstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's transient storage. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_WARM_ACCESS + |) ]] in + (* TODO statement *) + do* [[ state.set_transient_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "transient_storage" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/cancun/vm/instructions/system.ast b/coq/ethereum/cancun/vm/instructions/system.ast new file mode 100644 index 0000000000..63ad6f071b --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/system.ast @@ -0,0 +1,2952 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='is_account_alive'), + alias(name='move_ether'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='compute_create2_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError'), + alias(name='Revert'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_VALUE'), + alias(name='GAS_COLD_ACCOUNT_ACCESS'), + alias(name='GAS_CREATE'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='GAS_NEW_ACCOUNT'), + alias(name='GAS_SELF_DESTRUCT'), + alias(name='GAS_SELF_DESTRUCT_NEW_ACCOUNT'), + alias(name='GAS_WARM_ACCESS'), + alias(name='GAS_ZERO'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas'), + alias(name='init_code_cost'), + alias(name='max_message_call_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='generic_create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='endowment', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='contract_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='memory_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='init_code_gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Core logic used by the `CREATE*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='MAX_CODE_SIZE'), + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='call_data', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='MAX_CODE_SIZE', ctx=Load()))]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='contract_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='create_message_gas', ctx=Load())), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='is_static', + value=Constant(value=False)), + keyword( + arg='accessed_addresses', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='init_code_gas', ctx=Store())], + value=Call( + func=Name(id='init_code_cost', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())), + op=Add(), + right=Name(id='init_code_gas', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load()), + Name(id='init_code_gas', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create2', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Creates a new account with associated code.\n\n It's similar to CREATE opcode except that the address of new account\n depends on the init_code instead of the nonce of sender.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ")), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='salt', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='call_data_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='init_code_gas', ctx=Store())], + value=Call( + func=Name(id='init_code_cost', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='call_data_words', ctx=Load()))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())), + op=Add(), + right=Name(id='init_code_gas', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_create2_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='salt', ctx=Load()), + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load()), + Name(id='init_code_gas', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_staticcall', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=IfExp( + test=Name(id='is_staticcall', ctx=Load()), + body=Constant(value=True), + orelse=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()))), + keyword( + arg='accessed_addresses', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='to', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=BoolOp( + op=Or(), + values=[ + Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[]), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='access_gas_cost', ctx=Load()), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='code_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=Name(id='access_gas_cost', ctx=Load()), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SELF_DESTRUCT', ctx=Load())), + If( + test=Compare( + left=Name(id='beneficiary', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[])), + Compare( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Name(id='beneficiary', ctx=Load()), + Name(id='originator_balance', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='originator', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + attr='created_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='code_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='access_gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='staticcall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='to', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='access_gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='revert', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop execution and revert state changes, without consuming all provided gas\n and also has the ability to return a reason\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Name(id='output', ctx=Load())], + keywords=[])), + Raise( + exc=Name(id='Revert', ctx=Load())), + Pass()], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/instructions/system.v b/coq/ethereum/cancun/vm/instructions/system.v new file mode 100644 index 0000000000..69b4be5a7d --- /dev/null +++ b/coq/ethereum/cancun/vm/instructions/system.v @@ -0,0 +1,782 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.cancun.fork_types. +Require ethereum.cancun.state. +Require ethereum.cancun.utils.address. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.exceptions. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.memory. +Require ethereum.cancun.vm.stack. + +Definition generic_create (evm : Evm) (endowment : U256) (contract_address : Address) (memory_start_position : U256) (memory_size : U256) (init_code_gas : Uint) : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_start_position, + memory_size + |) in + ]] in + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "add" |) ~(| + contract_address + |) ]] in + do* M.assign "create_message_gas" [[ + gas.max_message_call_gas ~(| + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) in + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_local ~(| "create_message_gas" |) + ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ state.increment_nonce ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_create_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "init_code_gas" [[ + gas.init_code_cost ~(| + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "memory_size" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |), + M.get_local ~(| "init_code_gas" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition create2 (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "salt" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "call_data_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "init_code_gas" [[ + gas.init_code_cost ~(| + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "memory_size" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_create2_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "salt" |), + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |), + M.get_local ~(| "init_code_gas" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (is_staticcall : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_SELF_DESTRUCT in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.move_ether ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + M.get_local ~(| "beneficiary" |), + M.get_local ~(| "originator_balance" |) + |) ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + M.get_local ~(| "access_gas_cost" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition staticcall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + M.get_local ~(| "access_gas_cost" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "to" |), + M.get_local ~(| "to" |), + True, + True, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition revert (evm : Evm) : M unit := + (* + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "output" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/vm/interpreter.ast b/coq/ethereum/cancun/vm/interpreter.ast new file mode 100644 index 0000000000..4ec2cfea34 --- /dev/null +++ b/coq/ethereum/cancun/vm/interpreter.ast @@ -0,0 +1,1216 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Iterable'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='increment_nonce'), + alias(name='mark_account_created'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidContractPrefix'), + alias(name='InvalidOpcode'), + alias(name='OutOfGasError'), + alias(name='Revert'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_CODE_SIZE', ctx=Store())], + value=Constant(value=24576)), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `touched_accounts`: Accounts that have been touched.\n 6. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple(elts=[], ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='touched_accounts', + value=Name(id='touched_accounts', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.cancun.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='transient_storage', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='mark_account_created', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='contract_code', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=239)]), + body=[ + Raise( + exc=Name(id='InvalidContractPrefix', ctx=Load()))], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_CODE_SIZE', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='transient_storage', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='transient_storage', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='transient_storage', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.cancun.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='transient_storage', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='transient_storage', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='transient_storage', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='touched_accounts', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='return_data', + value=Constant(value=b'')), + keyword( + arg='error', + value=Constant(value=None)), + keyword( + arg='accessed_addresses', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='accessed_addresses', + ctx=Load())), + keyword( + arg='accessed_storage_keys', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))]), + ExceptHandler( + type=Name(id='Revert', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/interpreter.v b/coq/ethereum/cancun/vm/interpreter.v new file mode 100644 index 0000000000..8f59b48949 --- /dev/null +++ b/coq/ethereum/cancun/vm/interpreter.v @@ -0,0 +1,175 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.cancun.blocks. +Require ethereum.cancun.fork_types. +Require ethereum.cancun.state. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.precompiled_contracts.mapping. +Require ethereum.cancun.vm.__init__. +Require ethereum.cancun.vm.exceptions. +Require ethereum.cancun.vm.instructions. +Require ethereum.cancun.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.cancun.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| env, "transient_storage" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.mark_account_created ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.cancun.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| env, "transient_storage" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/vm/memory.ast b/coq/ethereum/cancun/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/cancun/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/memory.v b/coq/ethereum/cancun/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/cancun/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/__init__.ast b/coq/ethereum/cancun/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..cfca73a3bd --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,106 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS'), + Constant(value='MODEXP_ADDRESS'), + Constant(value='ALT_BN128_ADD_ADDRESS'), + Constant(value='ALT_BN128_MUL_ADDRESS'), + Constant(value='ALT_BN128_PAIRING_CHECK_ADDRESS'), + Constant(value='BLAKE2F_ADDRESS'), + Constant(value='POINT_EVALUATION_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[])), + Assign( + targets=[ + Name(id='MODEXP_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x05')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x06')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x07')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x08')], + keywords=[])), + Assign( + targets=[ + Name(id='BLAKE2F_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x09')], + keywords=[])), + Assign( + targets=[ + Name(id='POINT_EVALUATION_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x0a')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/__init__.v b/coq/ethereum/cancun/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..f2700ca5f5 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.cancun.utils.hexadecimal. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/alt_bn128.ast b/coq/ethereum/cancun/vm/precompiled_contracts/alt_bn128.ast new file mode 100644 index 0000000000..f6f077419c --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/alt_bn128.ast @@ -0,0 +1,913 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ALT_BN128 CONTRACTS\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ALT_BN128 precompiled contracts.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.alt_bn128', + names=[ + alias(name='ALT_BN128_CURVE_ORDER'), + alias(name='ALT_BN128_PRIME'), + alias(name='BNF'), + alias(name='BNF2'), + alias(name='BNF12'), + alias(name='BNP'), + alias(name='BNP2'), + alias(name='pairing')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=2), + FunctionDef( + name='alt_bn128_add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 addition precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=150)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load()), + Name(id='x1_value', ctx=Load()), + Name(id='y1_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='p1', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x1_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y1_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=BinOp( + left=Name(id='p0', ctx=Load()), + op=Add(), + right=Name(id='p1', ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 multiplication precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6000)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='n', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='p0', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='n', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_pairing_check', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 pairing check precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=34000), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))), + op=Add(), + right=Constant(value=45000))], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=192)), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='values', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=Name(id='j', ctx=Load()))), + upper=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=BinOp( + left=Name(id='j', ctx=Load()), + op=Add(), + right=Constant(value=1))))), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='values', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=Call( + func=Name(id='BNP2', ctx=Load()), + args=[ + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=3), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=2), + ctx=Load())], + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=5), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=4), + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='OutOfGasError', ctx=Load()), + args=[], + keywords=[]))])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='p', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='q', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='p', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + Compare( + left=Name(id='q', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='result', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='pairing', ctx=Load()), + args=[ + Name(id='q', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[])))], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='result', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/cancun/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000000..c63955b3ff --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,226 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.alt_bn128. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.memory. +Require ethereum.cancun.vm.exceptions. + +Definition alt_bn128_add (evm : Evm) : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 150 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "x1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x1_bytes" |) + |) + |) in + ]] in + do* M.assign "y1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y1_bytes" |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + (* TODO expression *) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_mul (evm : Evm) : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 6000 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "n" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + M.get_field ~(| M.get_local ~(| "p0" |), "mul_by" |) ~(| + M.get_local ~(| "n" |) + |) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_pairing_check (evm : Evm) : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + (* TODO expression *) + |) + |) ]] in + (* TODO statement *) + do* M.assign "result" [[ + M.get_field ~(| ethereum.crypto.alt_bn128.BNF12, "from_int" |) ~(| + 1 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/blake2f.ast b/coq/ethereum/cancun/vm/precompiled_contracts/blake2f.ast new file mode 100644 index 0000000000..03747962f0 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/blake2f.ast @@ -0,0 +1,137 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `Blake2` precompiled contract.\n')), + ImportFrom( + module='ethereum.crypto.blake2', + names=[ + alias(name='Blake2b')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BLAKE2_PER_ROUND'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidParameter')], + level=2), + FunctionDef( + name='blake2f', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the Blake2 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Constant(value=213)]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='blake2b', ctx=Store())], + value=Call( + func=Name(id='Blake2b', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='rounds', ctx=Store()), + Name(id='h', ctx=Store()), + Name(id='m', ctx=Store()), + Name(id='t_0', ctx=Store()), + Name(id='t_1', ctx=Store()), + Name(id='f', ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='get_blake2_parameters', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_BLAKE2_PER_ROUND', ctx=Load()), + op=Mult(), + right=Name(id='rounds', ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=Name(id='f', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + List( + elts=[ + Constant(value=0), + Constant(value=1)], + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='compress', + ctx=Load()), + args=[ + Name(id='rounds', ctx=Load()), + Name(id='h', ctx=Load()), + Name(id='m', ctx=Load()), + Name(id='t_0', ctx=Load()), + Name(id='t_1', ctx=Load()), + Name(id='f', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/blake2f.v b/coq/ethereum/cancun/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000000..86df041c8d --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,46 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +*) + +Require ethereum.crypto.blake2. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.exceptions. + +Definition blake2f (evm : Evm) : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + (* TODO statement *) + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| + + |) in + ]] in + (* TODO assignment *) + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/cancun/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/cancun/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..f3ea199717 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/identity.ast b/coq/ethereum/cancun/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/identity.v b/coq/ethereum/cancun/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..6c3123d4ee --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/mapping.ast b/coq/ethereum/cancun/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..298eeda974 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,105 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ALT_BN128_ADD_ADDRESS'), + alias(name='ALT_BN128_MUL_ADDRESS'), + alias(name='ALT_BN128_PAIRING_CHECK_ADDRESS'), + alias(name='BLAKE2F_ADDRESS'), + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='MODEXP_ADDRESS'), + alias(name='POINT_EVALUATION_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='alt_bn128', + names=[ + alias(name='alt_bn128_add'), + alias(name='alt_bn128_mul'), + alias(name='alt_bn128_pairing_check')], + level=1), + ImportFrom( + module='blake2f', + names=[ + alias(name='blake2f')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='modexp', + names=[ + alias(name='modexp')], + level=1), + ImportFrom( + module='point_evaluation', + names=[ + alias(name='point_evaluation')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load()), + Name(id='MODEXP_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Load()), + Name(id='BLAKE2F_ADDRESS', ctx=Load()), + Name(id='POINT_EVALUATION_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load()), + Name(id='modexp', ctx=Load()), + Name(id='alt_bn128_add', ctx=Load()), + Name(id='alt_bn128_mul', ctx=Load()), + Name(id='alt_bn128_pairing_check', ctx=Load()), + Name(id='blake2f', ctx=Load()), + Name(id='point_evaluation', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/mapping.v b/coq/ethereum/cancun/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..98fd18dbd7 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/mapping.v @@ -0,0 +1,26 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.cancun.fork_types. +Require ethereum.cancun.vm.precompiled_contracts.__init__. +Require ethereum.cancun.vm.precompiled_contracts.alt_bn128. +Require ethereum.cancun.vm.precompiled_contracts.blake2f. +Require ethereum.cancun.vm.precompiled_contracts.ecrecover. +Require ethereum.cancun.vm.precompiled_contracts.identity. +Require ethereum.cancun.vm.precompiled_contracts.modexp. +Require ethereum.cancun.vm.precompiled_contracts.point_evaluation. +Require ethereum.cancun.vm.precompiled_contracts.ripemd160. +Require ethereum.cancun.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/modexp.ast b/coq/ethereum/cancun/vm/precompiled_contracts/modexp.ast new file mode 100644 index 0000000000..42ecfa223f --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/modexp.ast @@ -0,0 +1,638 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `MODEXP` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + Assign( + targets=[ + Name(id='GQUADDIVISOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + FunctionDef( + name='modexp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and.\n `modulus`. The return value is the same length as the modulus.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='base_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_start', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Add(), + right=Name(id='base_length', ctx=Load()))), + Assign( + targets=[ + Name(id='exp_head', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Call( + func=Name(id='min', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='gas_cost', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load()), + Name(id='exp_length', ctx=Load()), + Name(id='exp_head', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='base_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='modulus_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Name(id='base_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_start', ctx=Store())], + value=BinOp( + left=Name(id='exp_start', ctx=Load()), + op=Add(), + right=Name(id='exp_length', ctx=Load()))), + Assign( + targets=[ + Name(id='modulus', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='modulus_start', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='modulus', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'\x00')], + keywords=[]), + op=Mult(), + right=Name(id='modulus_length', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exp', ctx=Load()), + Name(id='modulus', ctx=Load())], + keywords=[]), + attr='to_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[]), + Constant(value='big')], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='complexity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Estimate the complexity of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n Returns\n -------\n\n complexity : `Uint`\n Complexity of performing the operation.\n ')), + Assign( + targets=[ + Name(id='max_length', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load())], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Return( + value=BinOp( + left=Name(id='words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='iterations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the number of iterations required to perform a modular\n exponentiation.\n\n Parameters\n ----------\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n iterations : `Uint`\n Number of iterations.\n ')), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + Compare( + left=Name(id='exponent_head', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='bit_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='bit_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='bit_length', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Name(id='bit_length', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='length_part', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])))), + Assign( + targets=[ + Name(id='bits_part', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='bits_part', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='bits_part', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=BinOp( + left=Name(id='length_part', ctx=Load()), + op=Add(), + right=Name(id='bits_part', ctx=Load())))])]), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='count', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the gas cost of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n gas_cost : `Uint`\n Gas required for performing the operation.\n ')), + Assign( + targets=[ + Name(id='multiplication_complexity', ctx=Store())], + value=Call( + func=Name(id='complexity', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='iteration_count', ctx=Store())], + value=Call( + func=Name(id='iterations', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load()), + Name(id='exponent_head', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cost', ctx=Store())], + value=BinOp( + left=Name(id='multiplication_complexity', ctx=Load()), + op=Mult(), + right=Name(id='iteration_count', ctx=Load()))), + AugAssign( + target=Name(id='cost', ctx=Store()), + op=FloorDiv(), + value=Name(id='GQUADDIVISOR', ctx=Load())), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[]), + Name(id='cost', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/modexp.v b/coq/ethereum/cancun/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000000..ee22d9d2e5 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/modexp.v @@ -0,0 +1,236 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.gas. +Require ethereum.cancun.vm.memory. + +Definition modexp (evm : Evm) : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "base_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "modulus_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "exp_head" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "min" |) ~(| + ethereum_types.numeric.U256 ~(| + 32 + |), + M.get_local ~(| "exp_length" |) + |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) ~(| + M.get_local ~(| "base_length" |), + M.get_local ~(| "modulus_length" |), + M.get_local ~(| "exp_length" |), + M.get_local ~(| "exp_head" |) + |) + |) ]] in + (* TODO statement *) + do* M.assign "base" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + M.get_local ~(| "base_length" |) + |) + |) in + ]] in + do* M.assign "exp" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "exp_length" |) + |) + |) in + ]] in + do* M.assign "modulus_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "modulus" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "modulus_start" |), + M.get_local ~(| "modulus_length" |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := + (* + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + *) + do* M.assign "max_length" [[ + M.get_local ~(| "max" |) ~(| + ethereum_types.numeric.Uint ~(| + base_length + |), + ethereum_types.numeric.Uint ~(| + modulus_length + |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition gas_cost (base_length : U256) (modulus_length : U256) (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + *) + do* M.assign "multiplication_complexity" [[ + M.get_local ~(| "complexity" |) ~(| + base_length, + modulus_length + |) in + ]] in + do* M.assign "iteration_count" [[ + M.get_local ~(| "iterations" |) ~(| + exponent_length, + exponent_head + |) in + ]] in + do* M.assign "cost" [[ + (* TODO expression *) in + ]] in + do* M.aug_assign [[ M.get_local ~(| "cost" |) ]] [[ + M.get_local ~(| "GQUADDIVISOR" |) + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/point_evaluation.ast b/coq/ethereum/cancun/vm/precompiled_contracts/point_evaluation.ast new file mode 100644 index 0000000000..af245ad3c5 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/point_evaluation.ast @@ -0,0 +1,240 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) POINT EVALUATION PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the POINT EVALUATION precompiled contract.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes32'), + alias(name='Bytes48')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.kzg', + names=[ + alias(name='KZGCommitment'), + alias(name='kzg_commitment_to_versioned_hash'), + alias(name='verify_kzg_proof')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.exceptions', + names=[ + alias(name='KZGProofError')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_POINT_EVALUATION'), + alias(name='charge_gas')], + level=3), + Assign( + targets=[ + Name(id='FIELD_ELEMENTS_PER_BLOB', ctx=Store())], + value=Constant(value=4096)), + Assign( + targets=[ + Name(id='BLS_MODULUS', ctx=Store())], + value=Constant(value=52435875175126190479447740508185965837690552500527637822603658699938581184513)), + Assign( + targets=[ + Name(id='VERSIONED_HASH_VERSION_KZG', ctx=Store())], + value=Constant(value=b'\x01')), + FunctionDef( + name='point_evaluation', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n A pre-compile that verifies a KZG proof which claims that a blob\n (represented by a commitment) evaluates to a given value at a given point.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Constant(value=192)]), + body=[ + Raise( + exc=Name(id='KZGProofError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='versioned_hash', ctx=Store())], + value=Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Bytes32', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=Constant(value=32), + upper=Constant(value=64)), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Bytes32', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=Constant(value=64), + upper=Constant(value=96)), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='commitment', ctx=Store())], + value=Call( + func=Name(id='KZGCommitment', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=Constant(value=96), + upper=Constant(value=144)), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='proof', ctx=Store())], + value=Call( + func=Name(id='Bytes48', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=Constant(value=144), + upper=Constant(value=192)), + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_POINT_EVALUATION', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='kzg_commitment_to_versioned_hash', ctx=Load()), + args=[ + Name(id='commitment', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Name(id='versioned_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='KZGProofError', ctx=Load()))], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='kzg_proof_verification', ctx=Store())], + value=Call( + func=Name(id='verify_kzg_proof', ctx=Load()), + args=[ + Name(id='commitment', ctx=Load()), + Name(id='z', ctx=Load()), + Name(id='y', ctx=Load()), + Name(id='proof', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='Exception', ctx=Load()), + name='e', + body=[ + Raise( + exc=Name(id='KZGProofError', ctx=Load()), + cause=Name(id='e', ctx=Load()))])], + orelse=[], + finalbody=[]), + If( + test=UnaryOp( + op=Not(), + operand=Name(id='kzg_proof_verification', ctx=Load())), + body=[ + Raise( + exc=Name(id='KZGProofError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='FIELD_ELEMENTS_PER_BLOB', ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='BLS_MODULUS', ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/point_evaluation.v b/coq/ethereum/cancun/vm/precompiled_contracts/point_evaluation.v new file mode 100644 index 0000000000..089fae1b31 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/point_evaluation.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) POINT EVALUATION PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the POINT EVALUATION precompiled contract. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.kzg. +Require ethereum.cancun.vm. +Require ethereum.cancun.vm.exceptions. +Require ethereum.cancun.vm.gas. + +Definition point_evaluation (evm : Evm) : M unit := + (* + A pre-compile that verifies a KZG proof which claims that a blob + (represented by a commitment) evaluates to a given value at a given point. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + (* TODO statement *) + do* M.assign "versioned_hash" [[ + (* TODO expression *) in + ]] in + do* M.assign "z" [[ + ethereum_types.bytes.Bytes32 ~(| + (* TODO expression *) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.bytes.Bytes32 ~(| + (* TODO expression *) + |) in + ]] in + do* M.assign "commitment" [[ + ethereum.crypto.kzg.KZGCommitment ~(| + (* TODO expression *) + |) in + ]] in + do* M.assign "proof" [[ + ethereum_types.bytes.Bytes48 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_POINT_EVALUATION + |) ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/cancun/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/cancun/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/sha256.ast b/coq/ethereum/cancun/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/precompiled_contracts/sha256.v b/coq/ethereum/cancun/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/cancun/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/cancun/vm/runtime.ast b/coq/ethereum/cancun/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/cancun/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/runtime.v b/coq/ethereum/cancun/vm/runtime.v new file mode 100644 index 0000000000..877c7c9b74 --- /dev/null +++ b/coq/ethereum/cancun/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.cancun.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/cancun/vm/stack.ast b/coq/ethereum/cancun/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/cancun/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/cancun/vm/stack.v b/coq/ethereum/cancun/vm/stack.v new file mode 100644 index 0000000000..eb255bec67 --- /dev/null +++ b/coq/ethereum/cancun/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.cancun.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/__init__.ast b/coq/ethereum/constantinople/__init__.ast new file mode 100644 index 0000000000..92be3b14eb --- /dev/null +++ b/coq/ethereum/constantinople/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe Constantinople fork reduces mining rewards, delays the difficulty bomb,\nand introduces new EVM instructions for logical shifts, counterfactual\ncontract deployment, and computing bytecode hashes.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=7280000)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/__init__.v b/coq/ethereum/constantinople/__init__.v new file mode 100644 index 0000000000..70fadd17f8 --- /dev/null +++ b/coq/ethereum/constantinople/__init__.v @@ -0,0 +1,8 @@ +(* Generated *) +(* +The Constantinople fork reduces mining rewards, delays the difficulty bomb, +and introduces new EVM instructions for logical shifts, counterfactual +contract deployment, and computing bytecode hashes. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/constantinople/blocks.ast b/coq/ethereum/constantinople/blocks.ast new file mode 100644 index 0000000000..bcca95bdaa --- /dev/null +++ b/coq/ethereum/constantinople/blocks.ast @@ -0,0 +1,218 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mix_digest', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='succeeded', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/blocks.v b/coq/ethereum/constantinople/blocks.v new file mode 100644 index 0000000000..304641fa9a --- /dev/null +++ b/coq/ethereum/constantinople/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.constantinople.fork_types. +Require ethereum.constantinople.transactions. diff --git a/coq/ethereum/constantinople/bloom.ast b/coq/ethereum/constantinople/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/constantinople/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/bloom.v b/coq/ethereum/constantinople/bloom.v new file mode 100644 index 0000000000..5f84d0e4ec --- /dev/null +++ b/coq/ethereum/constantinople/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.constantinople.blocks. +Require ethereum.constantinople.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/fork.ast b/coq/ethereum/constantinople/fork.ast new file mode 100644 index 0000000000..1ccfe9527e --- /dev/null +++ b/coq/ethereum/constantinople/fork.ast @@ -0,0 +1,3186 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.ethash', + names=[ + alias(name='dataset_size'), + alias(name='generate_cache'), + alias(name='hashimoto_light')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty'), + alias(name='create_ether'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='Transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BLOCK_REWARD', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=18)))], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=131072)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_OMMER_DEPTH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='BOMB_DELAY_BLOCKS', ctx=Store())], + value=Constant(value=5000000)), + Assign( + targets=[ + Name(id='EMPTY_OMMER_HASH', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List(elts=[], ctx=Load())], + keywords=[])], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='validate_ommers', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='chain', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='chain', ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + Assign( + targets=[ + Name(id='parent_has_ommers', ctx=Store())], + value=Compare( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='EMPTY_OMMER_HASH', ctx=Load())])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_difficulty', ctx=Store())], + value=Call( + func=Name(id='calculate_block_difficulty', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Name(id='parent_has_ommers', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_difficulty', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='validate_proof_of_work', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generate_header_hash_for_pow', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate rlp hash of the header which is to be used for Proof-of-Work\n verification.\n\n In other words, the PoW artefacts `mix_digest` and `nonce` are ignored\n while calculating this hash.\n\n A particular PoW is valid for a single hash, that hash is computed by\n this function. The `nonce` and `mix_digest` are omitted from this hash\n because they are being changed by miners in their search for a sufficient\n proof-of-work.\n\n Parameters\n ----------\n header :\n The header object for which the hash is to be generated.\n\n Returns\n -------\n hash : `Hash32`\n The PoW valid rlp hash of the passed in header.\n ')), + Assign( + targets=[ + Name(id='header_data_without_pow_artefacts', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='state_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='transactions_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='receipt_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='bloom', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='header_data_without_pow_artefacts', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='validate_proof_of_work', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the Proof of Work constraints.\n\n In order to verify that a miner's proof-of-work is valid for a block, a\n ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``\n hash function. The mix digest is a hash of the header and the nonce that\n is passed through and it confirms whether or not proof-of-work was done\n on the correct block. The result is the actual hash value of the block.\n\n Parameters\n ----------\n header :\n Header of interest.\n ")), + Assign( + targets=[ + Name(id='header_hash', ctx=Store())], + value=Call( + func=Name(id='generate_header_hash_for_pow', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache', ctx=Store())], + value=Call( + func=Name(id='generate_cache', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='mix_digest', ctx=Store()), + Name(id='result', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='hashimoto_light', ctx=Load()), + args=[ + Name(id='header_hash', ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + Name(id='cache', ctx=Load()), + Call( + func=Name(id='dataset_size', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='mix_digest', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='mix_digest', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='limit', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='limit', ctx=Load()), + op=FloorDiv(), + right=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n gas_available :\n The gas remaining in the block.\n chain_id :\n The ID of the current chain.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + Return( + value=Name(id='sender_address', ctx=Load()))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='error', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n error :\n Error in the top level frame of the transaction, if any.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='succeeded', + value=Compare( + left=Name(id='error', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)])), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + Return( + value=Name(id='receipt', ctx=Load()))], + decorator_list=[], + returns=Name(id='Receipt', ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='block_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n block_difficulty :\n Difficulty of the block.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='transactions', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='tx', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='gas_available', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='gas_price', + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='difficulty', + value=Name(id='block_difficulty', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store()), + Name(id='error', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='error', ctx=Load()), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='pay_rewards', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='block_number', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='ommers', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='validate_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='block_header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the ommers mentioned in the block.\n\n An ommer block is a block that wasn't canonically added to the\n blockchain because it wasn't validated as fast as the canonical block\n but was mined at the same time.\n\n To be considered valid, the ommers must adhere to the rules defined in\n the Ethereum protocol. The maximum amount of ommers is 2 per block and\n there cannot be duplicate ommers in a block. Many of the other ommer\n constraints are listed in the in-line comments of this function.\n\n Parameters\n ----------\n ommers :\n List of ommers mentioned in the current block.\n block_header:\n The header of current block.\n chain :\n History and current state.\n ")), + Assign( + targets=[ + Name(id='block_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='block_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='ommers_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return()], + orelse=[]), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + op=Sub(), + right=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Name(id='ommer', ctx=Load()), + Name(id='ommer_parent_header', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=2)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommers_hashes', ctx=Store())], + value=ListComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + ifs=[], + is_async=0)])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[])], + keywords=[])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_canonical_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=BinOp( + left=Name(id='MAX_OMMER_DEPTH', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + ctx=Load())), + Assign( + targets=[ + Name(id='recent_canonical_block_hashes', ctx=Store())], + value=SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='recent_ommers_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + simple=1), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='recent_ommers_hashes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='recent_ommers_hashes', ctx=Load()), + attr='union', + ctx=Load()), + args=[ + SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='ommer_index', ctx=Store()), + Name(id='ommer', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='ommer_hash', ctx=Store())], + value=Subscript( + value=Name(id='ommers_hashes', ctx=Load()), + slice=Name(id='ommer_index', ctx=Load()), + ctx=Load())), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='block_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_ommers_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='ommer_age', ctx=Load())]), + Compare( + left=Name(id='ommer_age', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_OMMER_DEPTH', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='parent_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pay_rewards', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pay rewards to the block miner as well as the ommers miners.\n\n The miner of the canonical block is rewarded with the predetermined\n block reward, ``BLOCK_REWARD``, plus a variable award based off of the\n number of ommer blocks that were mined around the same time, and included\n in the canonical block's header. An ommer block is a block that wasn't\n added to the canonical blockchain because it wasn't validated as fast as\n the accepted block but was mined at the same time. Although not all blocks\n that are mined are added to the canonical chain, miners are still paid a\n reward for their efforts. This reward is called an ommer reward and is\n calculated based on the number associated with the ommer block that they\n mined.\n\n Parameters\n ----------\n state :\n Current account state.\n block_number :\n Position of the block within the chain.\n coinbase :\n Address of account which receives block reward and transaction fees.\n ommers :\n List of ommers mentioned in the current block.\n ")), + Assign( + targets=[ + Name(id='ommer_count', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='miner_reward', ctx=Store())], + value=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='ommer_count', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='miner_reward', ctx=Load())], + keywords=[])), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_number', ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='ommer_miner_reward', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Sub(), + right=Name(id='ommer_age', ctx=Load())), + op=Mult(), + right=Name(id='BLOCK_REWARD', ctx=Load())), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='ommer_miner_reward', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + If( + test=Compare( + left=Name(id='coinbase_balance_after_mining_fee', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]))], + orelse=[])]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='error', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Name(id='TX_CREATE_COST', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='v', ctx=Store()), + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=28)])]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash_pre155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='chain_id_x2', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=36)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[])), + op=Sub(), + right=Name(id='chain_id_x2', ctx=Load())), + Call( + func=Name(id='signing_hash_155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])], + keywords=[]))]), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash_pre155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a legacy (pre EIP 155) signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 155 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n The id of the current chain.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='chain_id', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_has_ommers', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes difficulty of a block using its header and parent header.\n\n The difficulty is determined by the time the block was created after its\n parent. The ``offset`` is calculated using the parent block's difficulty,\n ``parent_difficulty``, and the timestamp between blocks. This offset is\n then added to the parent difficulty and is stored as the ``difficulty``\n variable. If the time between the block and its parent is too short, the\n offset will result in a positive number thus making the sum of\n ``parent_difficulty`` and ``offset`` to be a greater value in order to\n avoid mass forking. But, if the time is long enough, then the offset\n results in a negative value making the block less difficult than\n its parent.\n\n The base standard for a block's difficulty is the predefined value\n set for the genesis block since it has no parent. So, a block\n can't be less difficult than the genesis block, therefore each block's\n difficulty is set to the maximum value between the calculated\n difficulty and the ``GENESIS_DIFFICULTY``.\n\n Parameters\n ----------\n block_number :\n Block number of the block.\n block_timestamp :\n Timestamp of the block.\n parent_timestamp :\n Timestamp of the parent block.\n parent_difficulty :\n difficulty of the parent block.\n parent_has_ommers:\n does the parent have ommers.\n\n Returns\n -------\n difficulty : `ethereum.base_types.Uint`\n Computed difficulty for a block.\n ")), + Assign( + targets=[ + Name(id='offset', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=2048)), + op=Mult(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=IfExp( + test=Name(id='parent_has_ommers', ctx=Load()), + body=Constant(value=2), + orelse=Constant(value=1)), + op=Sub(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_timestamp', ctx=Load()), + op=Sub(), + right=Name(id='parent_timestamp', ctx=Load()))], + keywords=[]), + op=FloorDiv(), + right=Constant(value=9))), + UnaryOp( + op=USub(), + operand=Constant(value=99))], + keywords=[]))), + Assign( + targets=[ + Name(id='difficulty', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='offset', ctx=Load()))), + Assign( + targets=[ + Name(id='num_bomb_periods', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='BOMB_DELAY_BLOCKS', ctx=Load())), + op=FloorDiv(), + right=Constant(value=100000)), + op=Sub(), + right=Constant(value=2))), + If( + test=Compare( + left=Name(id='num_bomb_periods', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='difficulty', ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Name(id='num_bomb_periods', ctx=Load())))], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='difficulty', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/fork.v b/coq/ethereum/constantinople/fork.v new file mode 100644 index 0000000000..09b0d5a7c7 --- /dev/null +++ b/coq/ethereum/constantinople/fork.v @@ -0,0 +1,847 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.ethash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.constantinople.__init__. +Require ethereum.constantinople.blocks. +Require ethereum.constantinople.bloom. +Require ethereum.constantinople.fork_types. +Require ethereum.constantinople.state. +Require ethereum.constantinople.transactions. +Require ethereum.constantinople.trie. +Require ethereum.constantinople.utils.message. +Require ethereum.constantinople.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + do* [[ M.get_local ~(| "validate_ommers" |) ~(| + M.get_field ~(| block, "ommers" |), + M.get_field ~(| block, "header" |), + chain + |) ]] in + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "difficulty" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| block, "ommers" |), + M.get_field ~(| chain, "chain_id" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + do* M.assign "parent_has_ommers" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_difficulty" [[ + M.get_local ~(| "calculate_block_difficulty" |) ~(| + M.get_field ~(| header, "number" |), + M.get_field ~(| header, "timestamp" |), + M.get_field ~(| parent_header, "timestamp" |), + M.get_field ~(| parent_header, "difficulty" |), + M.get_local ~(| "parent_has_ommers" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| + header + |) ]] in + M.pure tt. + +Definition generate_header_hash_for_pow (header : Header) : M Hash32 := + (* + 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. + *) + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_proof_of_work (header : Header) : M unit := + (* + 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. + *) + do* M.assign "header_hash" [[ + M.get_local ~(| "generate_header_hash_for_pow" |) ~(| + header + |) in + ]] in + do* M.assign "cache" [[ + ethereum.ethash.generate_cache ~(| + M.get_field ~(| header, "number" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (gas_available : Uint) (chain_id : U64) : M Address := + (* + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (error : (* TODO type *)) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (block_gas_limit : Uint) (block_time : U256) (block_difficulty : Uint) (transactions : (* TODO type *)) (ommers : (* TODO type *)) (chain_id : U64) : M ApplyBodyOutput := + (* + 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.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "pay_rewards" |) ~(| + state, + block_number, + coinbase, + ommers + |) ]] in + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_ommers (ommers : (* TODO type *)) (block_header : Header) (chain : BlockChain) : M unit := + (* + 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. + *) + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_canonical_blocks" [[ + (* TODO expression *) in + ]] in + do* M.assign "recent_canonical_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition pay_rewards (state : State) (block_number : Uint) (coinbase : Address) (ommers : (* TODO type *)) : M unit := + (* + 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. + *) + do* M.assign "ommer_count" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + ommers + |) + |) in + ]] in + do* M.assign "miner_reward" [[ + (* TODO expression *) in + ]] in + do* [[ state.create_ether ~(| + state, + coinbase, + M.get_local ~(| "miner_reward" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + do* M.assign "gas_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_pre155 (tx : Transaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_155 (tx : Transaction) (chain_id : U64) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_block_difficulty (block_number : Uint) (block_timestamp : U256) (parent_timestamp : U256) (parent_difficulty : Uint) (parent_has_ommers : bool) : M Uint := + (* + 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. + *) + do* M.assign "offset" [[ + (* TODO expression *) in + ]] in + do* M.assign "difficulty" [[ + (* TODO expression *) in + ]] in + do* M.assign "num_bomb_periods" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/fork_types.ast b/coq/ethereum/constantinople/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/constantinople/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/fork_types.v b/coq/ethereum/constantinople/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/constantinople/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/state.ast b/coq/ethereum/constantinople/state.ast new file mode 100644 index 0000000000..e39d5427ff --- /dev/null +++ b/coq/ethereum/constantinople/state.ast @@ -0,0 +1,1500 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has zero nonce, empty code and zero balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_empty : `bool`\n True if if an account has zero nonce, empty code and zero balance,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_exists_and_is_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists and has zero nonce, empty code and zero\n balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n exists_and_is_empty : `bool`\n True if an account exists and has zero nonce, empty code and zero\n balance, False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='account', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_alive', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether is an account is both in the state and non empty.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_alive : `bool`\n True if the account is alive.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[ + Return( + value=UnaryOp( + op=Not(), + operand=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])])))])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add newly created ether to an account.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to which ether is added.\n amount:\n The amount of ether to be added to the account of interest.\n ')), + FunctionDef( + name='increase_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/state.v b/coq/ethereum/constantinople/state.v new file mode 100644 index 0000000000..c860ca3d14 --- /dev/null +++ b/coq/ethereum/constantinople/state.v @@ -0,0 +1,562 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.constantinople.fork_types. +Require ethereum.constantinople.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_empty (state : State) (address : Address) : M bool := + (* + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition account_exists_and_is_empty (state : State) (address : Address) : M bool := + (* + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_alive (state : State) (address : Address) : M bool := + (* + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := + (* + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum/constantinople/transactions.ast b/coq/ethereum/constantinople/transactions.ast new file mode 100644 index 0000000000..19d5c9707f --- /dev/null +++ b/coq/ethereum/constantinople/transactions.ast @@ -0,0 +1,106 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + ClassDef( + name='Transaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/transactions.v b/coq/ethereum/constantinople/transactions.v new file mode 100644 index 0000000000..dd5bc0ca13 --- /dev/null +++ b/coq/ethereum/constantinople/transactions.v @@ -0,0 +1,13 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.constantinople.fork_types. diff --git a/coq/ethereum/constantinople/trie.ast b/coq/ethereum/constantinople/trie.ast new file mode 100644 index 0000000000..a998993acf --- /dev/null +++ b/coq/ethereum/constantinople/trie.ast @@ -0,0 +1,1618 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.byzantium', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.RLP`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/trie.v b/coq/ethereum/constantinople/trie.v new file mode 100644 index 0000000000..6b8953f256 --- /dev/null +++ b/coq/ethereum/constantinople/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/utils/__init__.ast b/coq/ethereum/constantinople/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/constantinople/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/utils/__init__.v b/coq/ethereum/constantinople/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/constantinople/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/constantinople/utils/address.ast b/coq/ethereum/constantinople/utils/address.ast new file mode 100644 index 0000000000..7571ffd780 --- /dev/null +++ b/coq/ethereum/constantinople/utils/address.ast @@ -0,0 +1,216 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this constantinople version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_create2_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='salt', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='call_data', + annotation=Name(id='bytearray', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created, which is\n based on the sender address, salt and the call data as well.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n salt :\n Address generation salt.\n call_data :\n The code of the new account which is to be created.\n\n Returns\n -------\n address: `ethereum.constantinople.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='preimage', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Constant(value=b'\xff'), + op=Add(), + right=Name(id='address', ctx=Load())), + op=Add(), + right=Name(id='salt', ctx=Load())), + op=Add(), + right=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='call_data', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/utils/address.v b/coq/ethereum/constantinople/utils/address.v new file mode 100644 index 0000000000..4cd9e16ff2 --- /dev/null +++ b/coq/ethereum/constantinople/utils/address.v @@ -0,0 +1,115 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this constantinople version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.constantinople.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition compute_create2_contract_address (address : Address) (salt : Bytes32) (call_data : bytearray) : M Address := + (* + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.constantinople.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "preimage" [[ + (* TODO expression *) in + ]] in + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "preimage" |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/utils/hexadecimal.ast b/coq/ethereum/constantinople/utils/hexadecimal.ast new file mode 100644 index 0000000000..1f8391c143 --- /dev/null +++ b/coq/ethereum/constantinople/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to\nConstantinople types.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/utils/hexadecimal.v b/coq/ethereum/constantinople/utils/hexadecimal.v new file mode 100644 index 0000000000..98728344f9 --- /dev/null +++ b/coq/ethereum/constantinople/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Constantinople types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.constantinople.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/utils/message.ast b/coq/ethereum/constantinople/utils/message.ast new file mode 100644 index 0000000000..0f97dd4d9c --- /dev/null +++ b/coq/ethereum/constantinople/utils/message.ast @@ -0,0 +1,241 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this constantinople version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_static', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True), + Constant(value=False)]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n is_static:\n if True then it prevents all state-changing operations from being\n executed.\n\n Returns\n -------\n message: `ethereum.constantinople.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=Name(id='is_static', ctx=Load())), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/utils/message.v b/coq/ethereum/constantinople/utils/message.v new file mode 100644 index 0000000000..e5fe6abc91 --- /dev/null +++ b/coq/ethereum/constantinople/utils/message.v @@ -0,0 +1,60 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this constantinople version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.constantinople.fork_types. +Require ethereum.constantinople.state. +Require ethereum.constantinople.vm. +Require ethereum.constantinople.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) (is_static : bool) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + + Returns + ------- + message: `ethereum.constantinople.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/__init__.ast b/coq/ethereum/constantinople/vm/__init__.ast new file mode 100644 index 0000000000..de465cd184 --- /dev/null +++ b/coq/ethereum/constantinople/vm/__init__.ast @@ -0,0 +1,509 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty')], + level=2), + ImportFrom( + module='precompiled_contracts', + names=[ + alias(name='RIPEMD160_ADDRESS')], + level=1), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='is_static', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='return_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + If( + test=Compare( + left=Name(id='RIPEMD160_ADDRESS', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/__init__.v b/coq/ethereum/constantinople/vm/__init__.v new file mode 100644 index 0000000000..23d6c2baca --- /dev/null +++ b/coq/ethereum/constantinople/vm/__init__.v @@ -0,0 +1,72 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.constantinople.blocks. +Require ethereum.constantinople.fork_types. +Require ethereum.constantinople.state. +Require ethereum.constantinople.vm.precompiled_contracts. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "touched_accounts" |), "update" |) ~(| + M.get_field ~(| child_evm, "touched_accounts" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + (* TODO statement *) + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/exceptions.ast b/coq/ethereum/constantinople/vm/exceptions.ast new file mode 100644 index 0000000000..ea06933e9c --- /dev/null +++ b/coq/ethereum/constantinople/vm/exceptions.ast @@ -0,0 +1,155 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='Revert', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised by the `REVERT` opcode.\n\n Unlike other EVM exceptions this does not result in the consumption of all\n gas.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='WriteInStaticContext', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt is made to modify the state while operating inside\n of a STATICCALL context.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfBoundsRead', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt was made to read data beyond the\n boundaries of the buffer.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/exceptions.v b/coq/ethereum/constantinople/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/constantinople/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/constantinople/vm/gas.ast b/coq/ethereum/constantinople/vm/gas.ast new file mode 100644 index 0000000000..86ad0672bc --- /dev/null +++ b/coq/ethereum/constantinople/vm/gas.ast @@ -0,0 +1,817 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXTERNAL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BALANCE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=400)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='REFUND_SELF_DESTRUCT', ctx=Store())], + value=Constant(value=24000)), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RETURN_DATA_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=400)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_left', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='memory_cost', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='extra_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='call_stipend', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Expr( + value=Constant(value='\n Calculates the MessageCallGas (cost and stipend) for\n executing call Opcodes.\n\n Parameters\n ----------\n value:\n The amount of `ETH` that needs to be transferred.\n gas :\n The amount of gas provided to the message-call.\n gas_left :\n The amount of gas left in the current frame.\n memory_cost :\n The amount needed to extend the memory in the current frame.\n extra_gas :\n The amount of gas needed for transferring value + creating a new\n account inside a message call.\n call_stipend :\n The amount of stipend provided to a message call to execute code while\n transferring value(ETH).\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='call_stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='call_stipend', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='extra_gas', ctx=Load()), + op=Add(), + right=Name(id='memory_cost', ctx=Load()))]), + body=[ + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='gas', ctx=Load()), + Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='gas_left', ctx=Load()), + op=Sub(), + right=Name(id='memory_cost', ctx=Load())), + op=Sub(), + right=Name(id='extra_gas', ctx=Load()))], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load())), + FunctionDef( + name='max_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the maximum gas that is allowed for making a message call\n\n Parameters\n ----------\n gas :\n The amount of gas provided to the message-call.\n\n Returns\n -------\n max_allowed_message_call_gas: `ethereum.base_types.Uint`\n The maximum gas allowed for making the message-call.\n ')), + Return( + value=BinOp( + left=Name(id='gas', ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='gas', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]))))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/gas.v b/coq/ethereum/constantinople/vm/gas.v new file mode 100644 index 0000000000..2ad12ff450 --- /dev/null +++ b/coq/ethereum/constantinople/vm/gas.v @@ -0,0 +1,171 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (value : U256) (gas : Uint) (gas_left : Uint) (memory_cost : Uint) (extra_gas : Uint) (call_stipend : Uint) : M MessageCallGas := + (* + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "gas" [[ + M.get_local ~(| "min" |) ~(| + gas, + M.get_local ~(| "max_message_call_gas" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition max_message_call_gas (gas : Uint) : M Uint := + (* + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/instructions/__init__.ast b/coq/ethereum/constantinople/vm/instructions/__init__.ast new file mode 100644 index 0000000000..2057f30486 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/__init__.ast @@ -0,0 +1,1756 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='SHL', ctx=Store())], + value=Constant(value=27)), + Assign( + targets=[ + Name(id='SHR', ctx=Store())], + value=Constant(value=28)), + Assign( + targets=[ + Name(id='SAR', ctx=Store())], + value=Constant(value=29)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='RETURNDATASIZE', ctx=Store())], + value=Constant(value=61)), + Assign( + targets=[ + Name(id='RETURNDATACOPY', ctx=Store())], + value=Constant(value=62)), + Assign( + targets=[ + Name(id='EXTCODEHASH', ctx=Store())], + value=Constant(value=63)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='DIFFICULTY', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='CREATE2', ctx=Store())], + value=Constant(value=245)), + Assign( + targets=[ + Name(id='STATICCALL', ctx=Store())], + value=Constant(value=250)), + Assign( + targets=[ + Name(id='REVERT', ctx=Store())], + value=Constant(value=253)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SAR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIFFICULTY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODEHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STATICCALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='REVERT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE2', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shl', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shr', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_sar', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodehash', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='staticcall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='revert', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create2', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/instructions/__init__.v b/coq/ethereum/constantinople/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/constantinople/vm/instructions/arithmetic.ast b/coq/ethereum/constantinople/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/instructions/arithmetic.v b/coq/ethereum/constantinople/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..d44c4fba13 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/instructions/bitwise.ast b/coq/ethereum/constantinople/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..b72397f0ec --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/bitwise.ast @@ -0,0 +1,751 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shl', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift left (SHL) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='value', ctx=Load()), + op=LShift(), + right=Name(id='shift', ctx=Load())), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]))], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shr', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift right (SHR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_sar', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Arithmetic shift right (SAR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='signed_value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=256)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + BinOp( + left=Name(id='signed_value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load()))], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='signed_value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load()))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/instructions/bitwise.v b/coq/ethereum/constantinople/vm/instructions/bitwise.v new file mode 100644 index 0000000000..f827d32b35 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/bitwise.v @@ -0,0 +1,309 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shl (evm : Evm) : M unit := + (* + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shr (evm : Evm) : M unit := + (* + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_sar (evm : Evm) : M unit := + (* + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + M.get_local ~(| "int" |) ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "signed_value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/instructions/block.ast b/coq/ethereum/constantinople/vm/instructions/block.ast new file mode 100644 index 0000000000..cc66857e82 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/block.ast @@ -0,0 +1,437 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's difficulty onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/instructions/block.v b/coq/ethereum/constantinople/vm/instructions/block.v new file mode 100644 index 0000000000..f4a4fea89b --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/block.v @@ -0,0 +1,213 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition difficulty (evm : Evm) : M unit := + (* + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/instructions/comparison.ast b/coq/ethereum/constantinople/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/instructions/comparison.v b/coq/ethereum/constantinople/vm/instructions/comparison.v new file mode 100644 index 0000000000..3ec417046c --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/instructions/control_flow.ast b/coq/ethereum/constantinople/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/instructions/control_flow.v b/coq/ethereum/constantinople/vm/instructions/control_flow.v new file mode 100644 index 0000000000..0482031065 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.exceptions. +Require ethereum.constantinople.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/instructions/environment.ast b/coq/ethereum/constantinople/vm/instructions/environment.ast new file mode 100644 index 0000000000..363044d482 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/environment.ast @@ -0,0 +1,1571 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfBoundsRead')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BALANCE'), + alias(name='GAS_BASE'), + alias(name='GAS_CODE_HASH'), + alias(name='GAS_COPY'), + alias(name='GAS_EXTERNAL'), + alias(name='GAS_RETURN_DATA_COPY'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BALANCE', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_EXTERNAL', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_EXTERNAL', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the size of the return data buffer onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copies data from the return data buffer code to memory\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='return_data_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_RETURN_DATA_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='return_data_start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfBoundsRead', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load()), + slice=Slice( + lower=Name(id='return_data_start_position', ctx=Load()), + upper=BinOp( + left=Name(id='return_data_start_position', ctx=Load()), + op=Add(), + right=Name(id='size', ctx=Load()))), + ctx=Load())), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodehash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns the keccak256 hash of a contract’s bytecode\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_CODE_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='EMPTY_ACCOUNT', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codehash', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/instructions/environment.v b/coq/ethereum/constantinople/vm/instructions/environment.v new file mode 100644 index 0000000000..b58ea5f63c --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/environment.v @@ -0,0 +1,680 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.constantinople.fork_types. +Require ethereum.constantinople.state. +Require ethereum.constantinople.utils.address. +Require ethereum.constantinople.vm.memory. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.exceptions. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BALANCE + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_EXTERNAL + |) ]] in + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatasize (evm : Evm) : M unit := + (* + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatacopy (evm : Evm) : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "return_data_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + (* TODO expression *) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodehash (evm : Evm) : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_CODE_HASH + |) ]] in + do* M.assign "account" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codehash" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/instructions/keccak.ast b/coq/ethereum/constantinople/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/instructions/keccak.v b/coq/ethereum/constantinople/vm/instructions/keccak.v new file mode 100644 index 0000000000..1479d39c1f --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.memory. +Require ethereum.constantinople.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/instructions/log.ast b/coq/ethereum/constantinople/vm/instructions/log.ast new file mode 100644 index 0000000000..0ded0e04ba --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/log.ast @@ -0,0 +1,323 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/instructions/log.v b/coq/ethereum/constantinople/vm/instructions/log.v new file mode 100644 index 0000000000..95129915df --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/log.v @@ -0,0 +1,79 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.constantinople.blocks. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.exceptions. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.memory. +Require ethereum.constantinople.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO statement *) + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/instructions/memory.ast b/coq/ethereum/constantinople/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/instructions/memory.v b/coq/ethereum/constantinople/vm/instructions/memory.v new file mode 100644 index 0000000000..3f4f66b424 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.memory. +Require ethereum.constantinople.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/instructions/stack.ast b/coq/ethereum/constantinople/vm/instructions/stack.ast new file mode 100644 index 0000000000..95cfc0b6cf --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/stack.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/instructions/stack.v b/coq/ethereum/constantinople/vm/instructions/stack.v new file mode 100644 index 0000000000..76776358a9 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/stack.v @@ -0,0 +1,153 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.exceptions. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/instructions/storage.ast b/coq/ethereum/constantinople/vm/instructions/storage.ast new file mode 100644 index 0000000000..0857eefb7e --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/storage.ast @@ -0,0 +1,295 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_SLOAD', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_UPDATE', ctx=Load()))]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/instructions/storage.v b/coq/ethereum/constantinople/vm/instructions/storage.v new file mode 100644 index 0000000000..c9dc5ee948 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/storage.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.constantinople.state. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.exceptions. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_SLOAD + |) ]] in + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/instructions/system.ast b/coq/ethereum/constantinople/vm/instructions/system.ast new file mode 100644 index 0000000000..6801ce9810 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/system.ast @@ -0,0 +1,2745 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='is_account_alive'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='compute_create2_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='Revert'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL'), + alias(name='GAS_CALL_VALUE'), + alias(name='GAS_CREATE'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='GAS_NEW_ACCOUNT'), + alias(name='GAS_SELF_DESTRUCT'), + alias(name='GAS_SELF_DESTRUCT_NEW_ACCOUNT'), + alias(name='GAS_ZERO'), + alias(name='REFUND_SELF_DESTRUCT'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas'), + alias(name='max_message_call_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='generic_create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='endowment', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='contract_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='memory_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Core logic used by the `CREATE*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='create_message_gas', ctx=Load())), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='is_static', + value=Constant(value=False)), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create2', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Creates a new account with associated code.\n\n It's similar to CREATE opcode except that the address of new account\n depends on the init_code instead of the nonce of sender.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ")), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='salt', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='call_data_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='call_data_words', ctx=Load()))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_create2_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='salt', ctx=Load()), + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_staticcall', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=IfExp( + test=Name(id='is_staticcall', ctx=Load()), + body=Constant(value=True), + orelse=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()))), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[])]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SELF_DESTRUCT', ctx=Load())), + If( + test=BoolOp( + op=And(), + values=[ + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[])), + Compare( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='refunded_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load())), + While( + test=Compare( + left=Name(id='parent_evm', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='refunded_accounts', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='originator', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='refunded_accounts', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Name(id='REFUND_SELF_DESTRUCT', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='GAS_CALL', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='staticcall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='GAS_CALL', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='revert', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop execution and revert state changes, without consuming all provided gas\n and also has the ability to return a reason\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Name(id='output', ctx=Load())], + keywords=[])), + Raise( + exc=Name(id='Revert', ctx=Load())), + Pass()], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/instructions/system.v b/coq/ethereum/constantinople/vm/instructions/system.v new file mode 100644 index 0000000000..85d02f3e65 --- /dev/null +++ b/coq/ethereum/constantinople/vm/instructions/system.v @@ -0,0 +1,779 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.constantinople.fork_types. +Require ethereum.constantinople.state. +Require ethereum.constantinople.utils.address. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.exceptions. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.memory. +Require ethereum.constantinople.vm.stack. + +Definition generic_create (evm : Evm) (endowment : U256) (contract_address : Address) (memory_start_position : U256) (memory_size : U256) : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* M.assign "create_message_gas" [[ + gas.max_message_call_gas ~(| + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) in + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_local ~(| "create_message_gas" |) + ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_start_position, + memory_size + |) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_create_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition create2 (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "salt" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "call_data_words" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_create2_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "salt" |), + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (is_staticcall : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_SELF_DESTRUCT in + ]] in + (* TODO statement *) + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "refunded_accounts" [[ + M.get_field ~(| evm, "accounts_to_delete" |) in + ]] in + do* M.assign "parent_evm" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "parent_evm" |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + gas.GAS_CALL + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition staticcall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + gas.GAS_CALL + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "to" |), + M.get_local ~(| "to" |), + True, + True, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition revert (evm : Evm) : M unit := + (* + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "output" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/interpreter.ast b/coq/ethereum/constantinople/vm/interpreter.ast new file mode 100644 index 0000000000..34a8743022 --- /dev/null +++ b/coq/ethereum/constantinople/vm/interpreter.ast @@ -0,0 +1,1123 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Iterable'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='increment_nonce'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidOpcode'), + alias(name='OutOfGasError'), + alias(name='Revert'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_CODE_SIZE', ctx=Store())], + value=Constant(value=24576)), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `touched_accounts`: Accounts that have been touched.\n 6. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='touched_accounts', + value=Name(id='touched_accounts', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.constantinople.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_CODE_SIZE', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.constantinople.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='touched_accounts', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='return_data', + value=Constant(value=b'')), + keyword( + arg='error', + value=Constant(value=None))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))]), + ExceptHandler( + type=Name(id='Revert', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/interpreter.v b/coq/ethereum/constantinople/vm/interpreter.v new file mode 100644 index 0000000000..cebe6f1599 --- /dev/null +++ b/coq/ethereum/constantinople/vm/interpreter.v @@ -0,0 +1,169 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.constantinople.blocks. +Require ethereum.constantinople.fork_types. +Require ethereum.constantinople.state. +Require ethereum.constantinople.vm. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.precompiled_contracts.mapping. +Require ethereum.constantinople.vm.__init__. +Require ethereum.constantinople.vm.exceptions. +Require ethereum.constantinople.vm.instructions. +Require ethereum.constantinople.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.constantinople.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.constantinople.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/memory.ast b/coq/ethereum/constantinople/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/constantinople/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/memory.v b/coq/ethereum/constantinople/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/constantinople/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/__init__.ast b/coq/ethereum/constantinople/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..f93208d0c0 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,89 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS'), + Constant(value='MODEXP_ADDRESS'), + Constant(value='ALT_BN128_ADD_ADDRESS'), + Constant(value='ALT_BN128_MUL_ADDRESS'), + Constant(value='ALT_BN128_PAIRING_CHECK_ADDRESS'), + Constant(value='BLAKE2F_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[])), + Assign( + targets=[ + Name(id='MODEXP_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x05')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x06')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x07')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x08')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/__init__.v b/coq/ethereum/constantinople/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..312d23906c --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.constantinople.utils.hexadecimal. diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.ast b/coq/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.ast new file mode 100644 index 0000000000..dd403eba17 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.ast @@ -0,0 +1,913 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ALT_BN128 CONTRACTS\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ALT_BN128 precompiled contracts.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.alt_bn128', + names=[ + alias(name='ALT_BN128_CURVE_ORDER'), + alias(name='ALT_BN128_PRIME'), + alias(name='BNF'), + alias(name='BNF2'), + alias(name='BNF12'), + alias(name='BNP'), + alias(name='BNP2'), + alias(name='pairing')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=2), + FunctionDef( + name='alt_bn128_add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 addition precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=500)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load()), + Name(id='x1_value', ctx=Load()), + Name(id='y1_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='p1', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x1_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y1_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=BinOp( + left=Name(id='p0', ctx=Load()), + op=Add(), + right=Name(id='p1', ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 multiplication precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=40000)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='n', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='p0', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='n', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_pairing_check', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 pairing check precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=80000), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))), + op=Add(), + right=Constant(value=100000))], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=192)), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='values', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=Name(id='j', ctx=Load()))), + upper=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=BinOp( + left=Name(id='j', ctx=Load()), + op=Add(), + right=Constant(value=1))))), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='values', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=Call( + func=Name(id='BNP2', ctx=Load()), + args=[ + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=3), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=2), + ctx=Load())], + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=5), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=4), + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='OutOfGasError', ctx=Load()), + args=[], + keywords=[]))])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='p', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='q', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='p', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + Compare( + left=Name(id='q', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='result', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='pairing', ctx=Load()), + args=[ + Name(id='q', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[])))], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='result', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000000..74c80d17bf --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,226 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.alt_bn128. +Require ethereum.constantinople.vm. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.memory. +Require ethereum.constantinople.vm.exceptions. + +Definition alt_bn128_add (evm : Evm) : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 500 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "x1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x1_bytes" |) + |) + |) in + ]] in + do* M.assign "y1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y1_bytes" |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + (* TODO expression *) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_mul (evm : Evm) : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 40000 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "n" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + M.get_field ~(| M.get_local ~(| "p0" |), "mul_by" |) ~(| + M.get_local ~(| "n" |) + |) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_pairing_check (evm : Evm) : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + (* TODO expression *) + |) + |) ]] in + (* TODO statement *) + do* M.assign "result" [[ + M.get_field ~(| ethereum.crypto.alt_bn128.BNF12, "from_int" |) ~(| + 1 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/constantinople/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/constantinople/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..774a2b92b7 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.constantinople.vm. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/identity.ast b/coq/ethereum/constantinople/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/identity.v b/coq/ethereum/constantinople/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..e5a3d27931 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.constantinople.vm. +Require ethereum.constantinople.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/mapping.ast b/coq/ethereum/constantinople/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..7d4dba4380 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,89 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ALT_BN128_ADD_ADDRESS'), + alias(name='ALT_BN128_MUL_ADDRESS'), + alias(name='ALT_BN128_PAIRING_CHECK_ADDRESS'), + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='MODEXP_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='alt_bn128', + names=[ + alias(name='alt_bn128_add'), + alias(name='alt_bn128_mul'), + alias(name='alt_bn128_pairing_check')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='modexp', + names=[ + alias(name='modexp')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load()), + Name(id='MODEXP_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load()), + Name(id='modexp', ctx=Load()), + Name(id='alt_bn128_add', ctx=Load()), + Name(id='alt_bn128_mul', ctx=Load()), + Name(id='alt_bn128_pairing_check', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/mapping.v b/coq/ethereum/constantinople/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..b87db86b50 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/mapping.v @@ -0,0 +1,24 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.constantinople.fork_types. +Require ethereum.constantinople.vm.precompiled_contracts.__init__. +Require ethereum.constantinople.vm.precompiled_contracts.alt_bn128. +Require ethereum.constantinople.vm.precompiled_contracts.ecrecover. +Require ethereum.constantinople.vm.precompiled_contracts.identity. +Require ethereum.constantinople.vm.precompiled_contracts.modexp. +Require ethereum.constantinople.vm.precompiled_contracts.ripemd160. +Require ethereum.constantinople.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/modexp.ast b/coq/ethereum/constantinople/vm/precompiled_contracts/modexp.ast new file mode 100644 index 0000000000..010c07fd00 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/modexp.ast @@ -0,0 +1,631 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `MODEXP` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + Assign( + targets=[ + Name(id='GQUADDIVISOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + FunctionDef( + name='modexp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and.\n `modulus`. The return value is the same length as the modulus.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='base_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_start', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Add(), + right=Name(id='base_length', ctx=Load()))), + Assign( + targets=[ + Name(id='exp_head', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Call( + func=Name(id='min', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='gas_cost', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load()), + Name(id='exp_length', ctx=Load()), + Name(id='exp_head', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='base_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='modulus_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Name(id='base_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_start', ctx=Store())], + value=BinOp( + left=Name(id='exp_start', ctx=Load()), + op=Add(), + right=Name(id='exp_length', ctx=Load()))), + Assign( + targets=[ + Name(id='modulus', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='modulus_start', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='modulus', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'\x00')], + keywords=[]), + op=Mult(), + right=Name(id='modulus_length', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exp', ctx=Load()), + Name(id='modulus', ctx=Load())], + keywords=[]), + attr='to_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[]), + Constant(value='big')], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='complexity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Estimate the complexity of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n Returns\n -------\n\n complexity : `Uint`\n Complexity of performing the operation.\n ')), + Assign( + targets=[ + Name(id='max_length', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load())], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='max_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[])]), + body=[ + Return( + value=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='max_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])]), + body=[ + Return( + value=BinOp( + left=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=4)], + keywords=[])), + op=Add(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Mult(), + right=Name(id='max_length', ctx=Load()))), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3072)], + keywords=[])))], + orelse=[ + Return( + value=BinOp( + left=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[])), + op=Add(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=480)], + keywords=[]), + op=Mult(), + right=Name(id='max_length', ctx=Load()))), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=199680)], + keywords=[])))])])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='iterations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the number of iterations required to perform a modular\n exponentiation.\n\n Parameters\n ----------\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n iterations : `Uint`\n Number of iterations.\n ')), + If( + test=Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='adjusted_exp_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Constant(value=0), + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + op=Sub(), + right=Constant(value=1))], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='adjusted_exp_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=8), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=32))), + op=Add(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + Constant(value=0), + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + op=Sub(), + right=Constant(value=1))], + keywords=[]))], + keywords=[]))]), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='adjusted_exp_length', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the gas cost of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n gas_cost : `Uint`\n Gas required for performing the operation.\n ')), + Assign( + targets=[ + Name(id='multiplication_complexity', ctx=Store())], + value=Call( + func=Name(id='complexity', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='iteration_count', ctx=Store())], + value=Call( + func=Name(id='iterations', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load()), + Name(id='exponent_head', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cost', ctx=Store())], + value=BinOp( + left=Name(id='multiplication_complexity', ctx=Load()), + op=Mult(), + right=Name(id='iteration_count', ctx=Load()))), + AugAssign( + target=Name(id='cost', ctx=Store()), + op=FloorDiv(), + value=Name(id='GQUADDIVISOR', ctx=Load())), + Return( + value=Name(id='cost', ctx=Load()))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/modexp.v b/coq/ethereum/constantinople/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000000..71b48ffd58 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/modexp.v @@ -0,0 +1,233 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.constantinople.vm. +Require ethereum.constantinople.vm.gas. +Require ethereum.constantinople.vm.memory. + +Definition modexp (evm : Evm) : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "base_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "modulus_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "exp_head" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "min" |) ~(| + ethereum_types.numeric.U256 ~(| + 32 + |), + M.get_local ~(| "exp_length" |) + |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) ~(| + M.get_local ~(| "base_length" |), + M.get_local ~(| "modulus_length" |), + M.get_local ~(| "exp_length" |), + M.get_local ~(| "exp_head" |) + |) + |) ]] in + (* TODO statement *) + do* M.assign "base" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + M.get_local ~(| "base_length" |) + |) + |) in + ]] in + do* M.assign "exp" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "exp_length" |) + |) + |) in + ]] in + do* M.assign "modulus_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "modulus" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "modulus_start" |), + M.get_local ~(| "modulus_length" |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := + (* + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + *) + do* M.assign "max_length" [[ + M.get_local ~(| "max" |) ~(| + ethereum_types.numeric.Uint ~(| + base_length + |), + ethereum_types.numeric.Uint ~(| + modulus_length + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition gas_cost (base_length : U256) (modulus_length : U256) (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + *) + do* M.assign "multiplication_complexity" [[ + M.get_local ~(| "complexity" |) ~(| + base_length, + modulus_length + |) in + ]] in + do* M.assign "iteration_count" [[ + M.get_local ~(| "iterations" |) ~(| + exponent_length, + exponent_head + |) in + ]] in + do* M.assign "cost" [[ + (* TODO expression *) in + ]] in + do* M.aug_assign [[ M.get_local ~(| "cost" |) ]] [[ + M.get_local ~(| "GQUADDIVISOR" |) + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/constantinople/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/constantinople/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/sha256.ast b/coq/ethereum/constantinople/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/precompiled_contracts/sha256.v b/coq/ethereum/constantinople/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/constantinople/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/runtime.ast b/coq/ethereum/constantinople/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/constantinople/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/runtime.v b/coq/ethereum/constantinople/vm/runtime.v new file mode 100644 index 0000000000..d33b7f5f4c --- /dev/null +++ b/coq/ethereum/constantinople/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.constantinople.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/constantinople/vm/stack.ast b/coq/ethereum/constantinople/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/constantinople/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/constantinople/vm/stack.v b/coq/ethereum/constantinople/vm/stack.v new file mode 100644 index 0000000000..16737d1820 --- /dev/null +++ b/coq/ethereum/constantinople/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.constantinople.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/crypto/__init__.ast b/coq/ethereum/crypto/__init__.ast new file mode 100644 index 0000000000..1143d8e590 --- /dev/null +++ b/coq/ethereum/crypto/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nCryptographic primitives used in Ethereum.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/crypto/__init__.v b/coq/ethereum/crypto/__init__.v new file mode 100644 index 0000000000..79dc6dbc57 --- /dev/null +++ b/coq/ethereum/crypto/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Cryptographic primitives used in Ethereum. +*) + diff --git a/coq/ethereum/crypto/alt_bn128.ast b/coq/ethereum/crypto/alt_bn128.ast new file mode 100644 index 0000000000..a77b8f288c --- /dev/null +++ b/coq/ethereum/crypto/alt_bn128.ast @@ -0,0 +1,1113 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe alt_bn128 curve\n^^^^^^^^^^^^^^^^^^^\n')), + ImportFrom( + names=[ + alias(name='elliptic_curve'), + alias(name='finite_field')], + level=1), + Assign( + targets=[ + Name(id='ALT_BN128_PRIME', ctx=Store())], + value=Constant(value=21888242871839275222246405745257275088696311157297823662689037894645226208583)), + Assign( + targets=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Store())], + value=Constant(value=21888242871839275222246405745257275088548364400416034343698204186575808495617)), + Assign( + targets=[ + Name(id='ATE_PAIRING_COUNT', ctx=Store())], + value=Constant(value=29793968203157093289)), + Assign( + targets=[ + Name(id='ATE_PAIRING_COUNT_BITS', ctx=Store())], + value=Constant(value=63)), + ClassDef( + name='BNF', + bases=[ + Attribute( + value=Name(id='finite_field', ctx=Load()), + attr='PrimeField', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The prime field over which the alt_bn128 curve is defined.\n ')), + Assign( + targets=[ + Name(id='PRIME', ctx=Store())], + value=Name(id='ALT_BN128_PRIME', ctx=Load()))], + decorator_list=[]), + ClassDef( + name='BNP', + bases=[ + Attribute( + value=Name(id='elliptic_curve', ctx=Load()), + attr='EllipticCurve', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The alt_bn128 curve.\n ')), + Assign( + targets=[ + Name(id='FIELD', ctx=Store())], + value=Name(id='BNF', ctx=Load())), + Assign( + targets=[ + Name(id='A', ctx=Store())], + value=Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='B', ctx=Store())], + value=Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[]))], + decorator_list=[]), + ClassDef( + name='BNF2', + bases=[ + Attribute( + value=Name(id='finite_field', ctx=Load()), + attr='GaloisField', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n `BNF` extended with a square root of 1 (`i`).\n ')), + Assign( + targets=[ + Name(id='PRIME', ctx=Store())], + value=Name(id='ALT_BN128_PRIME', ctx=Load())), + Assign( + targets=[ + Name(id='MODULUS', ctx=Store())], + value=Tuple( + elts=[ + Constant(value=1), + Constant(value=0)], + ctx=Load())), + AnnAssign( + target=Name(id='i', ctx=Store()), + annotation=Constant(value='BNF2'), + simple=1), + AnnAssign( + target=Name(id='i_plus_9', ctx=Store()), + annotation=Constant(value='BNF2'), + simple=1)], + decorator_list=[]), + Assign( + targets=[ + Attribute( + value=Name(id='BNF2', ctx=Load()), + attr='FROBENIUS_COEFFICIENTS', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF2', ctx=Load()), + attr='calculate_frobenius_coefficients', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Constant(value='autoapi_noindex')), + Assign( + targets=[ + Attribute( + value=Name(id='BNF2', ctx=Load()), + attr='i', + ctx=Store())], + value=Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Constant(value=0), + Constant(value=1)], + ctx=Load())], + keywords=[])), + Expr( + value=Constant(value='autoapi_noindex')), + Assign( + targets=[ + Attribute( + value=Name(id='BNF2', ctx=Load()), + attr='i_plus_9', + ctx=Store())], + value=Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Constant(value=9), + Constant(value=1)], + ctx=Load())], + keywords=[])), + Expr( + value=Constant(value='autoapi_noindex')), + ClassDef( + name='BNP2', + bases=[ + Attribute( + value=Name(id='elliptic_curve', ctx=Load()), + attr='EllipticCurve', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A twist of `BNP`. This is actually the same curve as `BNP` under a change\n of variable, but that change of variable is only possible over the larger\n field `BNP12`.\n ')), + Assign( + targets=[ + Name(id='FIELD', ctx=Store())], + value=Name(id='BNF2', ctx=Load())), + Assign( + targets=[ + Name(id='A', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF2', ctx=Load()), + attr='zero', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='B', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='BNF2', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=3)], + keywords=[]), + op=Div(), + right=BinOp( + left=Attribute( + value=Name(id='BNF2', ctx=Load()), + attr='i', + ctx=Load()), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='BNF2', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=9)], + keywords=[]))))], + decorator_list=[]), + ClassDef( + name='BNF12', + bases=[ + Attribute( + value=Name(id='finite_field', ctx=Load()), + attr='GaloisField', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n `BNF2` extended by adding a 6th root of `9 + i` called `w` (omega).\n ')), + Assign( + targets=[ + Name(id='PRIME', ctx=Store())], + value=Name(id='ALT_BN128_PRIME', ctx=Load())), + Assign( + targets=[ + Name(id='MODULUS', ctx=Store())], + value=Tuple( + elts=[ + Constant(value=82), + Constant(value=0), + Constant(value=0), + Constant(value=0), + Constant(value=0), + Constant(value=0), + UnaryOp( + op=USub(), + operand=Constant(value=18)), + Constant(value=0), + Constant(value=0), + Constant(value=0), + Constant(value=0), + Constant(value=0)], + ctx=Load())), + AnnAssign( + target=Name(id='w', ctx=Store()), + annotation=Constant(value='BNF12'), + simple=1), + AnnAssign( + target=Name(id='i_plus_9', ctx=Store()), + annotation=Constant(value='BNF12'), + simple=1), + FunctionDef( + name='__mul__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Constant(value='BNF12')), + arg( + arg='right', + annotation=Constant(value='BNF12'))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiplication special cased for BNF12.\n ')), + Assign( + targets=[ + Name(id='mul', ctx=Store())], + value=BinOp( + left=List( + elts=[ + Constant(value=0)], + ctx=Load()), + op=Mult(), + right=Constant(value=23))), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[]), + body=[ + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[]), + body=[ + AugAssign( + target=Subscript( + value=Name(id='mul', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Name(id='j', ctx=Load())), + ctx=Store()), + op=Add(), + value=BinOp( + left=Subscript( + value=Name(id='self', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + op=Mult(), + right=Subscript( + value=Name(id='right', ctx=Load()), + slice=Name(id='j', ctx=Load()), + ctx=Load())))], + orelse=[])], + orelse=[]), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=22), + Constant(value=11), + UnaryOp( + op=USub(), + operand=Constant(value=1))], + keywords=[]), + body=[ + AugAssign( + target=Subscript( + value=Name(id='mul', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Sub(), + right=Constant(value=6)), + ctx=Store()), + op=Sub(), + value=BinOp( + left=Subscript( + value=Name(id='mul', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + op=Mult(), + right=UnaryOp( + op=USub(), + operand=Constant(value=18)))), + AugAssign( + target=Subscript( + value=Name(id='mul', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Sub(), + right=Constant(value=12)), + ctx=Store()), + op=Sub(), + value=BinOp( + left=Subscript( + value=Name(id='mul', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + op=Mult(), + right=Constant(value=82)))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Name(id='BNF12', ctx=Load()), + Subscript( + value=Name(id='mul', ctx=Load()), + slice=Slice( + upper=Constant(value=12)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value='BNF12'))], + decorator_list=[]), + Assign( + targets=[ + Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='FROBENIUS_COEFFICIENTS', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='calculate_frobenius_coefficients', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Constant(value='autoapi_noindex')), + Assign( + targets=[ + Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='w', + ctx=Store())], + value=Call( + func=Name(id='BNF12', ctx=Load()), + args=[ + Tuple( + elts=[ + Constant(value=0), + Constant(value=1), + Constant(value=0), + Constant(value=0), + Constant(value=0), + Constant(value=0), + Constant(value=0), + Constant(value=0), + Constant(value=0), + Constant(value=0), + Constant(value=0), + Constant(value=0)], + ctx=Load())], + keywords=[])), + Expr( + value=Constant(value='autoapi_noindex')), + Assign( + targets=[ + Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='i_plus_9', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='w', + ctx=Load()), + op=Pow(), + right=Constant(value=6))), + Expr( + value=Constant(value='autoapi_noindex')), + ClassDef( + name='BNP12', + bases=[ + Attribute( + value=Name(id='elliptic_curve', ctx=Load()), + attr='EllipticCurve', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The same curve as `BNP`, but defined over the larger field. This curve has\n both subgroups of order `ALT_BN128_CURVE_ORDER` and allows pairings to be\n computed.\n ')), + Assign( + targets=[ + Name(id='FIELD', ctx=Store())], + value=Name(id='BNF12', ctx=Load())), + Assign( + targets=[ + Name(id='A', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='zero', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='B', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=3)], + keywords=[]))], + decorator_list=[]), + FunctionDef( + name='bnf2_to_bnf12', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='BNF2', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Lift a field element in `BNF2` to `BNF12`.\n ')), + Return( + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]), + op=Add(), + right=BinOp( + left=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='i_plus_9', + ctx=Load()), + op=Sub(), + right=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=9)], + keywords=[])))))], + decorator_list=[], + returns=Name(id='BNF12', ctx=Load())), + FunctionDef( + name='bnp_to_bnp12', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='p', + annotation=Name(id='BNP', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Lift a point from `BNP` to `BNP12`.\n ')), + Return( + value=Call( + func=Name(id='BNP12', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load())], + keywords=[])], + keywords=[]), + Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='BNP12', ctx=Load())), + FunctionDef( + name='twist', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='p', + annotation=Name(id='BNP2', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Apply to twist to change variables from the curve `BNP2` to `BNP12`.\n ')), + Return( + value=Call( + func=Name(id='BNP12', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bnf2_to_bnf12', ctx=Load()), + args=[ + Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='w', + ctx=Load()), + op=Pow(), + right=Constant(value=2))), + BinOp( + left=Call( + func=Name(id='bnf2_to_bnf12', ctx=Load()), + args=[ + Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='w', + ctx=Load()), + op=Pow(), + right=Constant(value=3)))], + keywords=[]))], + decorator_list=[], + returns=Name(id='BNP12', ctx=Load())), + FunctionDef( + name='linefunc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='p1', + annotation=Name(id='BNP12', ctx=Load())), + arg( + arg='p2', + annotation=Name(id='BNP12', ctx=Load())), + arg( + arg='t', + annotation=Name(id='BNP12', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Evaluate the function defining the line between points `p1` and `p2` at the\n point `t`. The mathematical significance of this function is that is has\n divisor `(p1) + (p2) + (p1 + p2) - 3(O)`.\n\n Note: Abstract mathematical presentations of Miller's algorithm often\n specify the divisor `(p1) + (p2) - (p1 + p2) - (O)`. This turns out not to\n matter.\n ")), + If( + test=Compare( + left=Attribute( + value=Name(id='p1', ctx=Load()), + attr='x', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='p2', ctx=Load()), + attr='x', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='lam', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='p2', ctx=Load()), + attr='y', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='p1', ctx=Load()), + attr='y', + ctx=Load())), + op=Div(), + right=BinOp( + left=Attribute( + value=Name(id='p2', ctx=Load()), + attr='x', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='p1', ctx=Load()), + attr='x', + ctx=Load())))), + Return( + value=BinOp( + left=BinOp( + left=Name(id='lam', ctx=Load()), + op=Mult(), + right=BinOp( + left=Attribute( + value=Name(id='t', ctx=Load()), + attr='x', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='p1', ctx=Load()), + attr='x', + ctx=Load()))), + op=Sub(), + right=BinOp( + left=Attribute( + value=Name(id='t', ctx=Load()), + attr='y', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='p1', ctx=Load()), + attr='y', + ctx=Load()))))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Name(id='p1', ctx=Load()), + attr='y', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='p2', ctx=Load()), + attr='y', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='lam', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=3)], + keywords=[]), + op=Mult(), + right=BinOp( + left=Attribute( + value=Name(id='p1', ctx=Load()), + attr='x', + ctx=Load()), + op=Pow(), + right=Constant(value=2))), + op=Div(), + right=BinOp( + left=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]), + op=Mult(), + right=Attribute( + value=Name(id='p1', ctx=Load()), + attr='y', + ctx=Load())))), + Return( + value=BinOp( + left=BinOp( + left=Name(id='lam', ctx=Load()), + op=Mult(), + right=BinOp( + left=Attribute( + value=Name(id='t', ctx=Load()), + attr='x', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='p1', ctx=Load()), + attr='x', + ctx=Load()))), + op=Sub(), + right=BinOp( + left=Attribute( + value=Name(id='t', ctx=Load()), + attr='y', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='p1', ctx=Load()), + attr='y', + ctx=Load()))))], + orelse=[ + Return( + value=BinOp( + left=Attribute( + value=Name(id='t', ctx=Load()), + attr='x', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='p1', ctx=Load()), + attr='x', + ctx=Load())))])])], + decorator_list=[], + returns=Name(id='BNF12', ctx=Load())), + FunctionDef( + name='miller_loop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='q', + annotation=Name(id='BNP12', ctx=Load())), + arg( + arg='p', + annotation=Name(id='BNP12', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The core of the pairing algorithm.\n ')), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='p', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP12', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + Compare( + left=Name(id='q', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP12', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])])]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Name(id='q', ctx=Load())), + Assign( + targets=[ + Name(id='f', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='ATE_PAIRING_COUNT_BITS', ctx=Load()), + UnaryOp( + op=USub(), + operand=Constant(value=1)), + UnaryOp( + op=USub(), + operand=Constant(value=1))], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='f', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='f', ctx=Load()), + op=Mult(), + right=Name(id='f', ctx=Load())), + op=Mult(), + right=Call( + func=Name(id='linefunc', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='r', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='r', ctx=Load()), + attr='double', + ctx=Load()), + args=[], + keywords=[])), + If( + test=BinOp( + left=BinOp( + left=Name(id='ATE_PAIRING_COUNT', ctx=Load()), + op=Sub(), + right=Constant(value=1)), + op=BitAnd(), + right=BinOp( + left=Constant(value=2), + op=Pow(), + right=Name(id='i', ctx=Load()))), + body=[ + Assign( + targets=[ + Name(id='f', ctx=Store())], + value=BinOp( + left=Name(id='f', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='linefunc', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='q', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=BinOp( + left=Name(id='r', ctx=Load()), + op=Add(), + right=Name(id='q', ctx=Load())))], + orelse=[])], + orelse=[]), + Assert( + test=Compare( + left=Name(id='r', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='q', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + BinOp( + left=Name(id='ATE_PAIRING_COUNT', ctx=Load()), + op=Sub(), + right=Constant(value=1))], + keywords=[])])), + Assign( + targets=[ + Name(id='q1', ctx=Store())], + value=Call( + func=Name(id='BNP12', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='q', ctx=Load()), + attr='x', + ctx=Load()), + attr='frobenius', + ctx=Load()), + args=[], + keywords=[]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='q', ctx=Load()), + attr='y', + ctx=Load()), + attr='frobenius', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='nq2', ctx=Store())], + value=Call( + func=Name(id='BNP12', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='q1', ctx=Load()), + attr='x', + ctx=Load()), + attr='frobenius', + ctx=Load()), + args=[], + keywords=[]), + UnaryOp( + op=USub(), + operand=Call( + func=Attribute( + value=Attribute( + value=Name(id='q1', ctx=Load()), + attr='y', + ctx=Load()), + attr='frobenius', + ctx=Load()), + args=[], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='f', ctx=Store())], + value=BinOp( + left=Name(id='f', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='linefunc', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='q1', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=BinOp( + left=Name(id='r', ctx=Load()), + op=Add(), + right=Name(id='q1', ctx=Load()))), + Assign( + targets=[ + Name(id='f', ctx=Store())], + value=BinOp( + left=Name(id='f', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='linefunc', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='nq2', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[]))), + Return( + value=BinOp( + left=Name(id='f', ctx=Load()), + op=Pow(), + right=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='ALT_BN128_PRIME', ctx=Load()), + op=Pow(), + right=Constant(value=12)), + op=Sub(), + right=Constant(value=1)), + op=FloorDiv(), + right=Name(id='ALT_BN128_CURVE_ORDER', ctx=Load()))))], + decorator_list=[], + returns=Name(id='BNF12', ctx=Load())), + FunctionDef( + name='pairing', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='q', + annotation=Name(id='BNP2', ctx=Load())), + arg( + arg='p', + annotation=Name(id='BNP', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the pairing of `q` and `p`.\n ')), + Return( + value=Call( + func=Name(id='miller_loop', ctx=Load()), + args=[ + Call( + func=Name(id='twist', ctx=Load()), + args=[ + Name(id='q', ctx=Load())], + keywords=[]), + Call( + func=Name(id='bnp_to_bnp12', ctx=Load()), + args=[ + Name(id='p', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='BNF12', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/crypto/alt_bn128.v b/coq/ethereum/crypto/alt_bn128.v new file mode 100644 index 0000000000..a2464bad7d --- /dev/null +++ b/coq/ethereum/crypto/alt_bn128.v @@ -0,0 +1,93 @@ +(* Generated *) +(* +The alt_bn128 curve +^^^^^^^^^^^^^^^^^^^ +*) + +Require ethereum.crypto.__init__. + +Definition bnf2_to_bnf12 (x : BNF2) : M BNF12 := + (* + Lift a field element in `BNF2` to `BNF12`. + *) + (* TODO statement *) + M.pure tt. + +Definition bnp_to_bnp12 (p : BNP) : M BNP12 := + (* + Lift a point from `BNP` to `BNP12`. + *) + (* TODO statement *) + M.pure tt. + +Definition twist (p : BNP2) : M BNP12 := + (* + Apply to twist to change variables from the curve `BNP2` to `BNP12`. + *) + (* TODO statement *) + M.pure tt. + +Definition linefunc (p1 : BNP12) (p2 : BNP12) (t : BNP12) : M BNF12 := + (* + Evaluate the function defining the line between points `p1` and `p2` at the + point `t`. The mathematical significance of this function is that is has + divisor `(p1) + (p2) + (p1 + p2) - 3(O)`. + + Note: Abstract mathematical presentations of Miller's algorithm often + specify the divisor `(p1) + (p2) - (p1 + p2) - (O)`. This turns out not to + matter. + *) + (* TODO statement *) + M.pure tt. + +Definition miller_loop (q : BNP12) (p : BNP12) : M BNF12 := + (* + The core of the pairing algorithm. + *) + (* TODO statement *) + do* M.assign "r" [[ + q in + ]] in + do* M.assign "f" [[ + M.get_field ~(| M.get_local ~(| "BNF12" |), "from_int" |) ~(| + 1 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "q1" [[ + M.get_local ~(| "BNP12" |) ~(| + M.get_field ~(| M.get_field ~(| q, "x" |), "frobenius" |) ~(| + + |), + M.get_field ~(| M.get_field ~(| q, "y" |), "frobenius" |) ~(| + + |) + |) in + ]] in + do* M.assign "nq2" [[ + M.get_local ~(| "BNP12" |) ~(| + M.get_field ~(| M.get_field ~(| M.get_local ~(| "q1" |), "x" |), "frobenius" |) ~(| + + |), + (* TODO expression *) + |) in + ]] in + do* M.assign "f" [[ + (* TODO expression *) in + ]] in + do* M.assign "r" [[ + (* TODO expression *) in + ]] in + do* M.assign "f" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition pairing (q : BNP2) (p : BNP) : M BNF12 := + (* + Compute the pairing of `q` and `p`. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/crypto/blake2.ast b/coq/ethereum/crypto/blake2.ast new file mode 100644 index 0000000000..80c22d572e --- /dev/null +++ b/coq/ethereum/crypto/blake2.ast @@ -0,0 +1,1714 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe Blake2 Implementation\n^^^^^^^^^^^^^^^^^^^^^^^^^^\n')), + Import( + names=[ + alias(name='struct')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Final'), + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + FunctionDef( + name='spit_le_to_uint', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Name(id='bytes', ctx=Load())), + arg( + arg='start', + annotation=Name(id='int', ctx=Load())), + arg( + arg='num_words', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Extracts 8 byte words from a given data.\n\n Parameters\n ----------\n data :\n The data in bytes from which the words need to be extracted\n start :\n Position to start the extraction\n num_words:\n The number of words to be extracted\n ')), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_words', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=BinOp( + left=Name(id='start', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=8)))), + Expr( + value=Call( + func=Attribute( + value=Name(id='words', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_le_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Name(id='start_position', ctx=Load()), + op=Add(), + right=Constant(value=8))), + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='words', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load())), + ClassDef( + name='Blake2', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Implementation of the BLAKE2 cryptographic hashing algorithm.\n\n Please refer the following document for details:\n https://datatracker.ietf.org/doc/html/rfc7693\n ')), + AnnAssign( + target=Name(id='w', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mask_bits', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='word_format', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='R1', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='R2', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='R3', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='R4', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + FunctionDef( + name='max_word', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Largest value for a given Blake2 flavor.\n ')), + Return( + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]), + op=Pow(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='w', + ctx=Load())))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='w_R1', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n (w - R1) value for a given Blake2 flavor.\n Used in the function G\n ')), + Return( + value=BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='w', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='R1', + ctx=Load())))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='w_R2', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n (w - R2) value for a given Blake2 flavor.\n Used in the function G\n ')), + Return( + value=BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='w', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='R2', + ctx=Load())))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='w_R3', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n (w - R3) value for a given Blake2 flavor.\n Used in the function G\n ')), + Return( + value=BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='w', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='R3', + ctx=Load())))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='w_R4', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n (w - R4) value for a given Blake2 flavor.\n Used in the function G\n ')), + Return( + value=BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='w', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='R4', + ctx=Load())))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Uint', ctx=Load())), + AnnAssign( + target=Name(id='sigma', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='int', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple( + elts=[ + Tuple( + elts=[ + Constant(value=0), + Constant(value=1), + Constant(value=2), + Constant(value=3), + Constant(value=4), + Constant(value=5), + Constant(value=6), + Constant(value=7), + Constant(value=8), + Constant(value=9), + Constant(value=10), + Constant(value=11), + Constant(value=12), + Constant(value=13), + Constant(value=14), + Constant(value=15)], + ctx=Load()), + Tuple( + elts=[ + Constant(value=14), + Constant(value=10), + Constant(value=4), + Constant(value=8), + Constant(value=9), + Constant(value=15), + Constant(value=13), + Constant(value=6), + Constant(value=1), + Constant(value=12), + Constant(value=0), + Constant(value=2), + Constant(value=11), + Constant(value=7), + Constant(value=5), + Constant(value=3)], + ctx=Load()), + Tuple( + elts=[ + Constant(value=11), + Constant(value=8), + Constant(value=12), + Constant(value=0), + Constant(value=5), + Constant(value=2), + Constant(value=15), + Constant(value=13), + Constant(value=10), + Constant(value=14), + Constant(value=3), + Constant(value=6), + Constant(value=7), + Constant(value=1), + Constant(value=9), + Constant(value=4)], + ctx=Load()), + Tuple( + elts=[ + Constant(value=7), + Constant(value=9), + Constant(value=3), + Constant(value=1), + Constant(value=13), + Constant(value=12), + Constant(value=11), + Constant(value=14), + Constant(value=2), + Constant(value=6), + Constant(value=5), + Constant(value=10), + Constant(value=4), + Constant(value=0), + Constant(value=15), + Constant(value=8)], + ctx=Load()), + Tuple( + elts=[ + Constant(value=9), + Constant(value=0), + Constant(value=5), + Constant(value=7), + Constant(value=2), + Constant(value=4), + Constant(value=10), + Constant(value=15), + Constant(value=14), + Constant(value=1), + Constant(value=11), + Constant(value=12), + Constant(value=6), + Constant(value=8), + Constant(value=3), + Constant(value=13)], + ctx=Load()), + Tuple( + elts=[ + Constant(value=2), + Constant(value=12), + Constant(value=6), + Constant(value=10), + Constant(value=0), + Constant(value=11), + Constant(value=8), + Constant(value=3), + Constant(value=4), + Constant(value=13), + Constant(value=7), + Constant(value=5), + Constant(value=15), + Constant(value=14), + Constant(value=1), + Constant(value=9)], + ctx=Load()), + Tuple( + elts=[ + Constant(value=12), + Constant(value=5), + Constant(value=1), + Constant(value=15), + Constant(value=14), + Constant(value=13), + Constant(value=4), + Constant(value=10), + Constant(value=0), + Constant(value=7), + Constant(value=6), + Constant(value=3), + Constant(value=9), + Constant(value=2), + Constant(value=8), + Constant(value=11)], + ctx=Load()), + Tuple( + elts=[ + Constant(value=13), + Constant(value=11), + Constant(value=7), + Constant(value=14), + Constant(value=12), + Constant(value=1), + Constant(value=3), + Constant(value=9), + Constant(value=5), + Constant(value=0), + Constant(value=15), + Constant(value=4), + Constant(value=8), + Constant(value=6), + Constant(value=2), + Constant(value=10)], + ctx=Load()), + Tuple( + elts=[ + Constant(value=6), + Constant(value=15), + Constant(value=14), + Constant(value=9), + Constant(value=11), + Constant(value=3), + Constant(value=0), + Constant(value=8), + Constant(value=12), + Constant(value=2), + Constant(value=13), + Constant(value=7), + Constant(value=1), + Constant(value=4), + Constant(value=10), + Constant(value=5)], + ctx=Load()), + Tuple( + elts=[ + Constant(value=10), + Constant(value=2), + Constant(value=8), + Constant(value=4), + Constant(value=7), + Constant(value=6), + Constant(value=1), + Constant(value=5), + Constant(value=15), + Constant(value=11), + Constant(value=9), + Constant(value=14), + Constant(value=3), + Constant(value=12), + Constant(value=13), + Constant(value=0)], + ctx=Load())], + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='IV', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple( + elts=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7640891576956012808)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=13503953896175478587)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=4354685564936845355)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=11912009170470909681)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5840696475078001361)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=11170449401992604703)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2270897969802886507)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6620516959819538809)], + keywords=[])], + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='MIX_TABLE', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Tuple( + elts=[ + Tuple( + elts=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=4)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])], + ctx=Load()), + Tuple( + elts=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=13)], + keywords=[])], + ctx=Load()), + Tuple( + elts=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=14)], + keywords=[])], + ctx=Load()), + Tuple( + elts=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=11)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])], + ctx=Load()), + Tuple( + elts=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])], + ctx=Load()), + Tuple( + elts=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=11)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])], + ctx=Load()), + Tuple( + elts=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=13)], + keywords=[])], + ctx=Load()), + Tuple( + elts=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=4)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=14)], + keywords=[])], + ctx=Load())], + ctx=Load()), + simple=1), + FunctionDef( + name='sigma_len', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Length of the sigma parameter.\n ')), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='sigma', + ctx=Load())], + keywords=[]))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='get_blake2_parameters', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='data', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Extract the parameters required in the Blake2 compression function\n from the provided bytes data.\n\n Parameters\n ----------\n data :\n The bytes data that has been passed in the message.\n ')), + Assign( + targets=[ + Name(id='rounds', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + upper=Constant(value=4)), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='h', ctx=Store())], + value=Call( + func=Name(id='spit_le_to_uint', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Constant(value=4), + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='m', ctx=Store())], + value=Call( + func=Name(id='spit_le_to_uint', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Constant(value=68), + Constant(value=16)], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='t_0', ctx=Store()), + Name(id='t_1', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='spit_le_to_uint', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Constant(value=196), + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='f', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=Constant(value=212)), + ctx=Load())], + keywords=[])), + Return( + value=Tuple( + elts=[ + Name(id='rounds', ctx=Load()), + Name(id='h', ctx=Load()), + Name(id='m', ctx=Load()), + Name(id='t_0', ctx=Load()), + Name(id='t_1', ctx=Load()), + Name(id='f', ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Name(id='Tuple', ctx=Load())), + FunctionDef( + name='G', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='v', + annotation=Name(id='List', ctx=Load())), + arg( + arg='a', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='c', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='d', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='x', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='y', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The mixing function used in Blake2\n https://datatracker.ietf.org/doc/html/rfc7693#section-3.1\n\n Parameters\n ----------\n v :\n The working vector to be mixed.\n a, b, c, d :\n Indexes within v of the words to be mixed.\n x, y :\n The two input words for the mixing.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='a', ctx=Load()), + ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='a', ctx=Load()), + ctx=Load()), + op=Add(), + right=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='b', ctx=Load()), + ctx=Load())), + op=Add(), + right=Name(id='x', ctx=Load())), + op=Mod(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='max_word', + ctx=Load()))), + Assign( + targets=[ + Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='d', ctx=Load()), + ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='d', ctx=Load()), + ctx=Load()), + op=BitXor(), + right=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='a', ctx=Load()), + ctx=Load())), + op=RShift(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='R1', + ctx=Load())), + op=BitXor(), + right=BinOp( + left=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='d', ctx=Load()), + ctx=Load()), + op=BitXor(), + right=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='a', ctx=Load()), + ctx=Load())), + op=LShift(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='w_R1', + ctx=Load())), + op=Mod(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='max_word', + ctx=Load())))), + Assign( + targets=[ + Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='c', ctx=Load()), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='c', ctx=Load()), + ctx=Load()), + op=Add(), + right=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='d', ctx=Load()), + ctx=Load())), + op=Mod(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='max_word', + ctx=Load()))), + Assign( + targets=[ + Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='b', ctx=Load()), + ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='b', ctx=Load()), + ctx=Load()), + op=BitXor(), + right=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='c', ctx=Load()), + ctx=Load())), + op=RShift(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='R2', + ctx=Load())), + op=BitXor(), + right=BinOp( + left=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='b', ctx=Load()), + ctx=Load()), + op=BitXor(), + right=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='c', ctx=Load()), + ctx=Load())), + op=LShift(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='w_R2', + ctx=Load())), + op=Mod(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='max_word', + ctx=Load())))), + Assign( + targets=[ + Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='a', ctx=Load()), + ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='a', ctx=Load()), + ctx=Load()), + op=Add(), + right=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='b', ctx=Load()), + ctx=Load())), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='max_word', + ctx=Load()))), + Assign( + targets=[ + Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='d', ctx=Load()), + ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='d', ctx=Load()), + ctx=Load()), + op=BitXor(), + right=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='a', ctx=Load()), + ctx=Load())), + op=RShift(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='R3', + ctx=Load())), + op=BitXor(), + right=BinOp( + left=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='d', ctx=Load()), + ctx=Load()), + op=BitXor(), + right=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='a', ctx=Load()), + ctx=Load())), + op=LShift(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='w_R3', + ctx=Load())), + op=Mod(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='max_word', + ctx=Load())))), + Assign( + targets=[ + Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='c', ctx=Load()), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='c', ctx=Load()), + ctx=Load()), + op=Add(), + right=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='d', ctx=Load()), + ctx=Load())), + op=Mod(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='max_word', + ctx=Load()))), + Assign( + targets=[ + Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='b', ctx=Load()), + ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='b', ctx=Load()), + ctx=Load()), + op=BitXor(), + right=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='c', ctx=Load()), + ctx=Load())), + op=RShift(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='R4', + ctx=Load())), + op=BitXor(), + right=BinOp( + left=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='b', ctx=Load()), + ctx=Load()), + op=BitXor(), + right=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='c', ctx=Load()), + ctx=Load())), + op=LShift(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='w_R4', + ctx=Load())), + op=Mod(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='max_word', + ctx=Load())))), + Return( + value=Name(id='v', ctx=Load()))], + decorator_list=[], + returns=Name(id='List', ctx=Load())), + FunctionDef( + name='compress', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='num_rounds', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='h', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load())), + arg( + arg='m', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load())), + arg( + arg='t_0', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='t_1', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='f', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n 'F Compression' from section 3.2 of RFC 7693:\n https://tools.ietf.org/html/rfc7693#section-3.2\n\n Parameters\n ----------\n num_rounds :\n The number of rounds. A 32-bit unsigned big-endian word\n h :\n The state vector. 8 unsigned 64-bit little-endian words\n m :\n The message block vector. 16 unsigned 64-bit little-endian words\n t_0, t_1 :\n Offset counters. 2 unsigned 64-bit little-endian words\n f:\n The final block indicator flag. An 8-bit word\n ")), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=BinOp( + left=List( + elts=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + ctx=Load()), + op=Mult(), + right=Constant(value=16))), + Assign( + targets=[ + Subscript( + value=Name(id='v', ctx=Load()), + slice=Slice( + lower=Constant(value=0), + upper=Constant(value=8)), + ctx=Store())], + value=Name(id='h', ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='v', ctx=Load()), + slice=Slice( + lower=Constant(value=8), + upper=Constant(value=15)), + ctx=Store())], + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='IV', + ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='v', ctx=Load()), + slice=Constant(value=12), + ctx=Store())], + value=BinOp( + left=Name(id='t_0', ctx=Load()), + op=BitXor(), + right=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='IV', + ctx=Load()), + slice=Constant(value=4), + ctx=Load()))), + Assign( + targets=[ + Subscript( + value=Name(id='v', ctx=Load()), + slice=Constant(value=13), + ctx=Store())], + value=BinOp( + left=Name(id='t_1', ctx=Load()), + op=BitXor(), + right=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='IV', + ctx=Load()), + slice=Constant(value=5), + ctx=Load()))), + If( + test=Name(id='f', ctx=Load()), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='v', ctx=Load()), + slice=Constant(value=14), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='v', ctx=Load()), + slice=Constant(value=14), + ctx=Load()), + op=BitXor(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='mask_bits', + ctx=Load())))], + orelse=[]), + For( + target=Name(id='r', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_rounds', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='sigma', + ctx=Load()), + slice=BinOp( + left=Name(id='r', ctx=Load()), + op=Mod(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='sigma_len', + ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='G', + ctx=Load()), + args=[ + Name(id='v', ctx=Load()), + Starred( + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='MIX_TABLE', + ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=1), + ctx=Load()), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='G', + ctx=Load()), + args=[ + Name(id='v', ctx=Load()), + Starred( + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='MIX_TABLE', + ctx=Load()), + slice=Constant(value=1), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=2), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=3), + ctx=Load()), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='G', + ctx=Load()), + args=[ + Name(id='v', ctx=Load()), + Starred( + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='MIX_TABLE', + ctx=Load()), + slice=Constant(value=2), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=4), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=5), + ctx=Load()), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='G', + ctx=Load()), + args=[ + Name(id='v', ctx=Load()), + Starred( + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='MIX_TABLE', + ctx=Load()), + slice=Constant(value=3), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=6), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=7), + ctx=Load()), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='G', + ctx=Load()), + args=[ + Name(id='v', ctx=Load()), + Starred( + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='MIX_TABLE', + ctx=Load()), + slice=Constant(value=4), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=8), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=9), + ctx=Load()), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='G', + ctx=Load()), + args=[ + Name(id='v', ctx=Load()), + Starred( + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='MIX_TABLE', + ctx=Load()), + slice=Constant(value=5), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=10), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=11), + ctx=Load()), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='G', + ctx=Load()), + args=[ + Name(id='v', ctx=Load()), + Starred( + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='MIX_TABLE', + ctx=Load()), + slice=Constant(value=6), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=12), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=13), + ctx=Load()), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='G', + ctx=Load()), + args=[ + Name(id='v', ctx=Load()), + Starred( + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='MIX_TABLE', + ctx=Load()), + slice=Constant(value=7), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=14), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='m', ctx=Load()), + slice=Subscript( + value=Name(id='s', ctx=Load()), + slice=Constant(value=15), + ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='result_message_words', ctx=Store())], + value=GeneratorExp( + elt=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='h', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + op=BitXor(), + right=Subscript( + value=Name(id='v', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=BitXor(), + right=Subscript( + value=Name(id='v', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=8)), + ctx=Load())), + generators=[ + comprehension( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + ifs=[], + is_async=0)])), + Return( + value=Call( + func=Attribute( + value=Name(id='struct', ctx=Load()), + attr='pack', + ctx=Load()), + args=[ + BinOp( + left=Constant(value='<8%s'), + op=Mod(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='word_format', + ctx=Load())), + Starred( + value=Name(id='result_message_words', ctx=Load()), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='bytes', ctx=Load()))], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Blake2b', + bases=[ + Name(id='Blake2', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Blake2b flavor (64-bits) of Blake2.\n This version is used in the pre-compiled contract.\n ')), + AnnAssign( + target=Name(id='w', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + simple=1), + AnnAssign( + target=Name(id='mask_bits', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=18446744073709551615)], + keywords=[]), + simple=1), + AnnAssign( + target=Name(id='word_format', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + value=Constant(value='Q'), + simple=1), + AnnAssign( + target=Name(id='R1', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + simple=1), + AnnAssign( + target=Name(id='R2', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=24)], + keywords=[]), + simple=1), + AnnAssign( + target=Name(id='R3', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + simple=1), + AnnAssign( + target=Name(id='R4', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=63)], + keywords=[]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/crypto/blake2.v b/coq/ethereum/crypto/blake2.v new file mode 100644 index 0000000000..de14103999 --- /dev/null +++ b/coq/ethereum/crypto/blake2.v @@ -0,0 +1,26 @@ +(* Generated *) +(* +The Blake2 Implementation +^^^^^^^^^^^^^^^^^^^^^^^^^^ +*) + + +Definition spit_le_to_uint (data : bytes) (start : int) (num_words : int) : M (* TODO type *) := + (* + Extracts 8 byte words from a given data. + + Parameters + ---------- + data : + The data in bytes from which the words need to be extracted + start : + Position to start the extraction + num_words: + The number of words to be extracted + *) + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/crypto/elliptic_curve.ast b/coq/ethereum/crypto/elliptic_curve.ast new file mode 100644 index 0000000000..3ccaa45389 --- /dev/null +++ b/coq/ethereum/crypto/elliptic_curve.ast @@ -0,0 +1,967 @@ +Module( + body=[ + Expr( + value=Constant(value='\nElliptic Curves\n^^^^^^^^^^^^^^^\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Generic'), + alias(name='Type'), + alias(name='TypeVar')], + level=0), + Import( + names=[ + alias(name='coincurve')]), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='finite_field', + names=[ + alias(name='Field')], + level=1), + ImportFrom( + module='hash', + names=[ + alias(name='Hash32')], + level=1), + Assign( + targets=[ + Name(id='SECP256K1N', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=115792089237316195423570985008687907852837564279074904382605163141518161494337)], + keywords=[])), + Assign( + targets=[ + Name(id='F', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='F')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Field', ctx=Load()))])), + Assign( + targets=[ + Name(id='T', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='T')], + keywords=[ + keyword( + arg='bound', + value=Constant(value='EllipticCurve'))])), + FunctionDef( + name='secp256k1_recover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='r', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='s', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='v', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='msg_hash', + annotation=Name(id='Hash32', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Recovers the public key from a given signature.\n\n Parameters\n ----------\n r :\n TODO\n s :\n TODO\n v :\n TODO\n msg_hash :\n Hash of the message being recovered.\n\n Returns\n -------\n public_key : `ethereum.base_types.Bytes`\n Recovered public key.\n ')), + Assign( + targets=[ + Name(id='r_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='r', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='s_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='s', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='signature', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=0)], + ctx=Load()), + op=Mult(), + right=Constant(value=65))], + keywords=[])), + Assign( + targets=[ + Subscript( + value=Name(id='signature', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=32), + op=Sub(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='r_bytes', ctx=Load())], + keywords=[])), + upper=Constant(value=32)), + ctx=Store())], + value=Name(id='r_bytes', ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='signature', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=64), + op=Sub(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='s_bytes', ctx=Load())], + keywords=[])), + upper=Constant(value=64)), + ctx=Store())], + value=Name(id='s_bytes', ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='signature', ctx=Load()), + slice=Constant(value=64), + ctx=Store())], + value=Name(id='v', ctx=Load())), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='coincurve', ctx=Load()), + attr='PublicKey', + ctx=Load()), + attr='from_signature_and_message', + ctx=Load()), + args=[ + Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Name(id='signature', ctx=Load())], + keywords=[]), + Name(id='msg_hash', ctx=Load())], + keywords=[ + keyword( + arg='hasher', + value=Constant(value=None))])), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Subscript( + value=Call( + func=Attribute( + value=Name(id='public_key', ctx=Load()), + attr='format', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='compressed', + value=Constant(value=False))]), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())), + Return( + value=Name(id='public_key', ctx=Load()))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='EllipticCurve', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Name(id='F', ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Superclass for integers modulo a prime. Not intended to be used\n directly, but rather to be subclassed.\n ')), + Assign( + targets=[ + Name(id='__slots__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='x'), + Constant(value='y')], + ctx=Load())), + AnnAssign( + target=Name(id='FIELD', ctx=Store()), + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='F', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='A', ctx=Store()), + annotation=Name(id='F', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='B', ctx=Store()), + annotation=Name(id='F', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='x', ctx=Store()), + annotation=Name(id='F', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y', ctx=Store()), + annotation=Name(id='F', ctx=Load()), + simple=1), + FunctionDef( + name='__new__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='T', ctx=Load()), + ctx=Load())), + arg( + arg='x', + annotation=Name(id='F', ctx=Load())), + arg( + arg='y', + annotation=Name(id='F', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make new point on the curve. The point is not checked to see if it is\n on the curve.\n ')), + Assign( + targets=[ + Name(id='res', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='object', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Name(id='cls', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='res', ctx=Load()), + attr='x', + ctx=Store())], + value=Name(id='x', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='res', ctx=Load()), + attr='y', + ctx=Store())], + value=Name(id='y', ctx=Load())), + Return( + value=Name(id='res', ctx=Load()))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='x', + annotation=Name(id='F', ctx=Load())), + arg( + arg='y', + annotation=Name(id='F', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the point is on the curve. To skip this check call\n `__new__()` directly.\n ')), + If( + test=BoolOp( + op=And(), + values=[ + BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='FIELD', + ctx=Load()), + attr='zero', + ctx=Load()), + args=[], + keywords=[])]), + Compare( + left=Name(id='y', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='FIELD', + ctx=Load()), + attr='zero', + ctx=Load()), + args=[], + keywords=[])])]), + Compare( + left=BinOp( + left=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='y', ctx=Load()), + op=Pow(), + right=Constant(value=2)), + op=Sub(), + right=BinOp( + left=Name(id='x', ctx=Load()), + op=Pow(), + right=Constant(value=3))), + op=Sub(), + right=BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='A', + ctx=Load()), + op=Mult(), + right=Name(id='x', ctx=Load()))), + op=Sub(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='B', + ctx=Load())), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='FIELD', + ctx=Load()), + attr='zero', + ctx=Load()), + args=[], + keywords=[])])]), + body=[ + Raise( + exc=Call( + func=Name(id='ValueError', ctx=Load()), + args=[ + Constant(value='Point not on curve')], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='__eq__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='other', + annotation=Name(id='object', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Test two points for equality.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='other', ctx=Load()), + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[])], + keywords=[])), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='x', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='other', ctx=Load()), + attr='x', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='y', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='other', ctx=Load()), + attr='y', + ctx=Load())])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='__str__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stringify a point as its coordinates.\n ')), + Return( + value=Call( + func=Name(id='str', ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='x', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='y', + ctx=Load())], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='str', ctx=Load())), + FunctionDef( + name='point_at_infinity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='T', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Return the point at infinity. This is the identity element of the group\n operation.\n\n The point at infinity doesn't actually have coordinates so we use\n `(0, 0)` (which isn't on the curve) to represent it.\n ")), + Return( + value=Call( + func=Attribute( + value=Name(id='cls', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Name(id='cls', ctx=Load()), + Call( + func=Attribute( + value=Attribute( + value=Name(id='cls', ctx=Load()), + attr='FIELD', + ctx=Load()), + attr='zero', + ctx=Load()), + args=[], + keywords=[]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='cls', ctx=Load()), + attr='FIELD', + ctx=Load()), + attr='zero', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + decorator_list=[ + Name(id='classmethod', ctx=Load())], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='double', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a point to itself.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='x', ctx=Store()), + Name(id='y', ctx=Store()), + Name(id='F', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='x', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='y', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='FIELD', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Return( + value=Name(id='self', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='lam', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Attribute( + value=Name(id='F', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=3)], + keywords=[]), + op=Mult(), + right=BinOp( + left=Name(id='x', ctx=Load()), + op=Pow(), + right=Constant(value=2))), + op=Add(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='A', + ctx=Load())), + op=Div(), + right=BinOp( + left=Call( + func=Attribute( + value=Name(id='F', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]), + op=Mult(), + right=Name(id='y', ctx=Load())))), + Assign( + targets=[ + Name(id='new_x', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='lam', ctx=Load()), + op=Pow(), + right=Constant(value=2)), + op=Sub(), + right=Name(id='x', ctx=Load())), + op=Sub(), + right=Name(id='x', ctx=Load()))), + Assign( + targets=[ + Name(id='new_y', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='lam', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='x', ctx=Load()), + op=Sub(), + right=Name(id='new_x', ctx=Load()))), + op=Sub(), + right=Name(id='y', ctx=Load()))), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + Name(id='new_x', ctx=Load()), + Name(id='new_y', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='__add__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load())), + arg( + arg='other', + annotation=Name(id='T', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add two points together.\n ')), + Assign( + targets=[ + Name(id='ZERO', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='FIELD', + ctx=Load()), + attr='zero', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='self_x', ctx=Store()), + Name(id='self_y', ctx=Store()), + Name(id='other_x', ctx=Store()), + Name(id='other_y', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='x', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='y', + ctx=Load()), + Attribute( + value=Name(id='other', ctx=Load()), + attr='x', + ctx=Load()), + Attribute( + value=Name(id='other', ctx=Load()), + attr='y', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='self_x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='ZERO', ctx=Load())]), + Compare( + left=Name(id='self_y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='ZERO', ctx=Load())])]), + body=[ + Return( + value=Name(id='other', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='other_x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='ZERO', ctx=Load())]), + Compare( + left=Name(id='other_y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='ZERO', ctx=Load())])]), + body=[ + Return( + value=Name(id='self', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='self_x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='other_x', ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='self_y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='other_y', ctx=Load())]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='double', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[]))])], + orelse=[]), + Assign( + targets=[ + Name(id='lam', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='other_y', ctx=Load()), + op=Sub(), + right=Name(id='self_y', ctx=Load())), + op=Div(), + right=BinOp( + left=Name(id='other_x', ctx=Load()), + op=Sub(), + right=Name(id='self_x', ctx=Load())))), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='lam', ctx=Load()), + op=Pow(), + right=Constant(value=2)), + op=Sub(), + right=Name(id='self_x', ctx=Load())), + op=Sub(), + right=Name(id='other_x', ctx=Load()))), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='lam', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='self_x', ctx=Load()), + op=Sub(), + right=Name(id='x', ctx=Load()))), + op=Sub(), + right=Name(id='self_y', ctx=Load()))), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + Name(id='x', ctx=Load()), + Name(id='y', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='mul_by', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load())), + arg( + arg='n', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply `self` by `n` using the double and add algorithm.\n ')), + Assign( + targets=[ + Name(id='res', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='FIELD', + ctx=Load()), + attr='zero', + ctx=Load()), + args=[], + keywords=[]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='FIELD', + ctx=Load()), + attr='zero', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Name(id='self', ctx=Load())), + While( + test=Compare( + left=Name(id='n', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + If( + test=Compare( + left=BinOp( + left=Name(id='n', ctx=Load()), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='res', ctx=Store())], + value=BinOp( + left=Name(id='res', ctx=Load()), + op=Add(), + right=Name(id='s', ctx=Load())))], + orelse=[]), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=BinOp( + left=Name(id='s', ctx=Load()), + op=Add(), + right=Name(id='s', ctx=Load()))), + AugAssign( + target=Name(id='n', ctx=Store()), + op=FloorDiv(), + value=Constant(value=2))], + orelse=[]), + Return( + value=Name(id='res', ctx=Load()))], + decorator_list=[], + returns=Name(id='T', ctx=Load()))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/crypto/elliptic_curve.v b/coq/ethereum/crypto/elliptic_curve.v new file mode 100644 index 0000000000..9a857622c7 --- /dev/null +++ b/coq/ethereum/crypto/elliptic_curve.v @@ -0,0 +1,59 @@ +(* Generated *) +(* +Elliptic Curves +^^^^^^^^^^^^^^^ +*) + +Require typing. + +Definition secp256k1_recover (r : U256) (s : U256) (v : U256) (msg_hash : Hash32) : M Bytes := + (* + Recovers the public key from a given signature. + + Parameters + ---------- + r : + TODO + s : + TODO + v : + TODO + msg_hash : + Hash of the message being recovered. + + Returns + ------- + public_key : `ethereum.base_types.Bytes` + Recovered public key. + *) + do* M.assign "r_bytes" [[ + M.get_field ~(| r, "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "s_bytes" [[ + M.get_field ~(| s, "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "signature" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO assignment *) + do* M.assign "public_key" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "coincurve" |), "PublicKey" |), "from_signature_and_message" |) ~(| + M.get_local ~(| "bytes" |) ~(| + M.get_local ~(| "signature" |) + |), + msg_hash + |) in + ]] in + do* M.assign "public_key" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/crypto/finite_field.ast b/coq/ethereum/crypto/finite_field.ast new file mode 100644 index 0000000000..ada3510c33 --- /dev/null +++ b/coq/ethereum/crypto/finite_field.ast @@ -0,0 +1,2896 @@ +Module( + body=[ + Expr( + value=Constant(value='\nFinite Fields\n^^^^^^^^^^^^^\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Iterable'), + alias(name='List'), + alias(name='Tuple'), + alias(name='Type'), + alias(name='TypeVar'), + alias(name='cast')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='typing_extensions', + names=[ + alias(name='Protocol')], + level=0), + Assign( + targets=[ + Name(id='F', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='F')], + keywords=[ + keyword( + arg='bound', + value=Constant(value='Field'))])), + ClassDef( + name='Field', + bases=[ + Name(id='Protocol', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A type protocol for defining fields.\n ')), + Assign( + targets=[ + Name(id='__slots__', ctx=Store())], + value=Tuple(elts=[], ctx=Load())), + FunctionDef( + name='zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='F', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value=Ellipsis))], + decorator_list=[ + Name(id='classmethod', ctx=Load())], + returns=Name(id='F', ctx=Load())), + FunctionDef( + name='from_int', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='F', ctx=Load()), + ctx=Load())), + arg( + arg='n', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value=Ellipsis))], + decorator_list=[ + Name(id='classmethod', ctx=Load())], + returns=Name(id='F', ctx=Load())), + FunctionDef( + name='__radd__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='F', ctx=Load())), + arg( + arg='left', + annotation=Name(id='F', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value=Ellipsis))], + decorator_list=[], + returns=Name(id='F', ctx=Load())), + FunctionDef( + name='__add__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='F', ctx=Load())), + arg( + arg='right', + annotation=Name(id='F', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value=Ellipsis))], + decorator_list=[], + returns=Name(id='F', ctx=Load())), + FunctionDef( + name='__iadd__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='F', ctx=Load())), + arg( + arg='right', + annotation=Name(id='F', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value=Ellipsis))], + decorator_list=[], + returns=Name(id='F', ctx=Load())), + FunctionDef( + name='__sub__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='F', ctx=Load())), + arg( + arg='right', + annotation=Name(id='F', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value=Ellipsis))], + decorator_list=[], + returns=Name(id='F', ctx=Load())), + FunctionDef( + name='__rsub__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='F', ctx=Load())), + arg( + arg='left', + annotation=Name(id='F', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value=Ellipsis))], + decorator_list=[], + returns=Name(id='F', ctx=Load())), + FunctionDef( + name='__mul__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='F', ctx=Load())), + arg( + arg='right', + annotation=Name(id='F', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value=Ellipsis))], + decorator_list=[], + returns=Name(id='F', ctx=Load())), + FunctionDef( + name='__rmul__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='F', ctx=Load())), + arg( + arg='left', + annotation=Name(id='F', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value=Ellipsis))], + decorator_list=[], + returns=Name(id='F', ctx=Load())), + FunctionDef( + name='__imul__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='F', ctx=Load())), + arg( + arg='right', + annotation=Name(id='F', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value=Ellipsis))], + decorator_list=[], + returns=Name(id='F', ctx=Load())), + FunctionDef( + name='__pow__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='F', ctx=Load())), + arg( + arg='exponent', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value=Ellipsis))], + decorator_list=[], + returns=Name(id='F', ctx=Load())), + FunctionDef( + name='__ipow__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='F', ctx=Load())), + arg( + arg='right', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value=Ellipsis))], + decorator_list=[], + returns=Name(id='F', ctx=Load())), + FunctionDef( + name='__neg__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='F', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value=Ellipsis))], + decorator_list=[], + returns=Name(id='F', ctx=Load())), + FunctionDef( + name='__truediv__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='F', ctx=Load())), + arg( + arg='right', + annotation=Name(id='F', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value=Ellipsis))], + decorator_list=[], + returns=Name(id='F', ctx=Load()))], + decorator_list=[]), + Assign( + targets=[ + Name(id='T', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='T')], + keywords=[ + keyword( + arg='bound', + value=Constant(value='PrimeField'))])), + ClassDef( + name='PrimeField', + bases=[ + Name(id='int', ctx=Load()), + Name(id='Field', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Superclass for integers modulo a prime. Not intended to be used\n directly, but rather to be subclassed.\n ')), + Assign( + targets=[ + Name(id='__slots__', ctx=Store())], + value=Tuple(elts=[], ctx=Load())), + AnnAssign( + target=Name(id='PRIME', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='from_be_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='T', ctx=Load()), + ctx=Load())), + arg( + arg='buffer', + annotation=Constant(value='Bytes'))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a sequence of bytes into a element of the field.\n Parameters\n ----------\n buffer :\n Bytes to decode.\n Returns\n -------\n self : `T`\n Unsigned integer decoded from `buffer`.\n ')), + Return( + value=Call( + func=Name(id='cls', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='int', ctx=Load()), + attr='from_bytes', + ctx=Load()), + args=[ + Name(id='buffer', ctx=Load()), + Constant(value='big')], + keywords=[])], + keywords=[]))], + decorator_list=[ + Name(id='classmethod', ctx=Load())], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='T', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='cls', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Name(id='cls', ctx=Load()), + Constant(value=0)], + keywords=[]))], + decorator_list=[ + Name(id='classmethod', ctx=Load())], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='from_int', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='T', ctx=Load()), + ctx=Load())), + arg( + arg='n', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='cls', ctx=Load()), + args=[ + Name(id='n', ctx=Load())], + keywords=[]))], + decorator_list=[ + Name(id='classmethod', ctx=Load())], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='__new__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='T', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='int', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Name(id='cls', ctx=Load()), + BinOp( + left=Name(id='value', ctx=Load()), + op=Mod(), + right=Attribute( + value=Name(id='cls', ctx=Load()), + attr='PRIME', + ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='__radd__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load())), + arg( + arg='left', + annotation=Name(id='T', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__add__', + ctx=Load()), + args=[ + Name(id='left', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='__add__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load())), + arg( + arg='right', + annotation=Name(id='T', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='right', ctx=Load()), + Name(id='int', ctx=Load())], + keywords=[])), + body=[ + Return( + value=Name(id='NotImplemented', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + Call( + func=Attribute( + value=Name(id='int', ctx=Load()), + attr='__add__', + ctx=Load()), + args=[ + Name(id='self', ctx=Load()), + Name(id='right', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='__iadd__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load())), + arg( + arg='right', + annotation=Name(id='T', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__add__', + ctx=Load()), + args=[ + Name(id='right', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='__sub__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load())), + arg( + arg='right', + annotation=Name(id='T', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='right', ctx=Load()), + Name(id='int', ctx=Load())], + keywords=[])), + body=[ + Return( + value=Name(id='NotImplemented', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + Call( + func=Attribute( + value=Name(id='int', ctx=Load()), + attr='__sub__', + ctx=Load()), + args=[ + Name(id='self', ctx=Load()), + Name(id='right', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='__rsub__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load())), + arg( + arg='left', + annotation=Name(id='T', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='left', ctx=Load()), + Name(id='int', ctx=Load())], + keywords=[])), + body=[ + Return( + value=Name(id='NotImplemented', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + Call( + func=Attribute( + value=Name(id='int', ctx=Load()), + attr='__rsub__', + ctx=Load()), + args=[ + Name(id='self', ctx=Load()), + Name(id='left', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='__mul__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load())), + arg( + arg='right', + annotation=Name(id='T', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='right', ctx=Load()), + Name(id='int', ctx=Load())], + keywords=[])), + body=[ + Return( + value=Name(id='NotImplemented', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + Call( + func=Attribute( + value=Name(id='int', ctx=Load()), + attr='__mul__', + ctx=Load()), + args=[ + Name(id='self', ctx=Load()), + Name(id='right', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='__rmul__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load())), + arg( + arg='left', + annotation=Name(id='T', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__mul__', + ctx=Load()), + args=[ + Name(id='left', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='__imul__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load())), + arg( + arg='right', + annotation=Name(id='T', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__mul__', + ctx=Load()), + args=[ + Name(id='right', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + Assign( + targets=[ + Name(id='__floordiv__', ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Name(id='__rfloordiv__', ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Name(id='__ifloordiv__', ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Name(id='__divmod__', ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Name(id='__rdivmod__', ctx=Store())], + value=Constant(value=None)), + FunctionDef( + name='__pow__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load())), + arg( + arg='exponent', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + Call( + func=Attribute( + value=Name(id='int', ctx=Load()), + attr='__pow__', + ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + Name(id='exponent', ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='PRIME', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + Assign( + targets=[ + Name(id='__rpow__', ctx=Store())], + value=Constant(value=None)), + FunctionDef( + name='__ipow__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load())), + arg( + arg='right', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__pow__', + ctx=Load()), + args=[ + Name(id='right', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + Assign( + targets=[ + Name(id='__and__', ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Name(id='__or__', ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Name(id='__xor__', ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Name(id='__rxor__', ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Name(id='__ixor__', ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Name(id='__rshift__', ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Name(id='__lshift__', ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Name(id='__irshift__', ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Name(id='__ilshift__', ctx=Store())], + value=Constant(value=None)), + FunctionDef( + name='__neg__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + Call( + func=Attribute( + value=Name(id='int', ctx=Load()), + attr='__neg__', + ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='__truediv__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load())), + arg( + arg='right', + annotation=Name(id='T', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=BinOp( + left=Name(id='self', ctx=Load()), + op=Mult(), + right=Call( + func=Attribute( + value=Name(id='right', ctx=Load()), + attr='multiplicative_inverse', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='multiplicative_inverse', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='T', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=BinOp( + left=Name(id='self', ctx=Load()), + op=Pow(), + right=UnaryOp( + op=USub(), + operand=Constant(value=1))))], + decorator_list=[], + returns=Name(id='T', ctx=Load())), + FunctionDef( + name='to_be_bytes32', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts this arbitrarily sized unsigned integer into its big endian\n representation with exactly 32 bytes.\n Returns\n -------\n big_endian : `Bytes32`\n Big endian (most significant bits first) representation.\n ')), + Return( + value=Call( + func=Name(id='Bytes32', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='to_bytes', + ctx=Load()), + args=[ + Constant(value=32), + Constant(value='big')], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value='Bytes32'))], + decorator_list=[]), + Assign( + targets=[ + Name(id='U', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='U')], + keywords=[ + keyword( + arg='bound', + value=Constant(value='GaloisField'))])), + ClassDef( + name='GaloisField', + bases=[ + Name(id='tuple', ctx=Load()), + Name(id='Field', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Superclass for defining finite fields. Not intended to be used\n directly, but rather to be subclassed.\n\n Fields are represented as `F_p[x]/(x^n + ...)` where the `MODULUS` is a\n tuple of the non-leading coefficients of the defining polynomial. For\n example `x^3 + 2x^2 + 3x + 4` is `(2, 3, 4)`.\n\n In practice the polynomial is likely to be sparse and you should overload\n the `__mul__()` function to take advantage of this fact.\n ')), + Assign( + targets=[ + Name(id='__slots__', ctx=Store())], + value=Tuple(elts=[], ctx=Load())), + AnnAssign( + target=Name(id='PRIME', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='MODULUS', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='int', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='FROBENIUS_COEFFICIENTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Constant(value='GaloisField'), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + FunctionDef( + name='zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='U', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='cls', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Name(id='cls', ctx=Load()), + BinOp( + left=List( + elts=[ + Constant(value=0)], + ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='cls', ctx=Load()), + attr='MODULUS', + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[ + Name(id='classmethod', ctx=Load())], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='from_int', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='U', ctx=Load()), + ctx=Load())), + arg( + arg='n', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='cls', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Name(id='cls', ctx=Load()), + BinOp( + left=List( + elts=[ + Name(id='n', ctx=Load())], + ctx=Load()), + op=Add(), + right=BinOp( + left=List( + elts=[ + Constant(value=0)], + ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='cls', ctx=Load()), + attr='MODULUS', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1))))], + keywords=[]))], + decorator_list=[ + Name(id='classmethod', ctx=Load())], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='__new__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='U', ctx=Load()), + ctx=Load())), + arg( + arg='iterable', + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='self', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='tuple', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Name(id='cls', ctx=Load()), + GeneratorExp( + elt=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Attribute( + value=Name(id='cls', ctx=Load()), + attr='PRIME', + ctx=Load())), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Name(id='iterable', ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[])), + Assert( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='cls', ctx=Load()), + attr='MODULUS', + ctx=Load())], + keywords=[])])), + Return( + value=Name(id='self', ctx=Load()))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='__add__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load())), + arg( + arg='right', + annotation=Name(id='U', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='right', ctx=Load()), + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[])], + keywords=[])), + body=[ + Return( + value=Name(id='NotImplemented', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + GeneratorExp( + elt=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='x', ctx=Store()), + Name(id='y', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='cast', ctx=Load()), + args=[ + Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='int', ctx=Load()), + Name(id='int', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Call( + func=Name(id='zip', ctx=Load()), + args=[ + Name(id='self', ctx=Load()), + Name(id='right', ctx=Load())], + keywords=[])], + keywords=[]), + ifs=[], + is_async=0)])], + keywords=[]))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='__radd__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load())), + arg( + arg='left', + annotation=Name(id='U', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__add__', + ctx=Load()), + args=[ + Name(id='left', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='__iadd__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load())), + arg( + arg='right', + annotation=Name(id='U', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__add__', + ctx=Load()), + args=[ + Name(id='right', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='__sub__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load())), + arg( + arg='right', + annotation=Name(id='U', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='right', ctx=Load()), + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[])], + keywords=[])), + body=[ + Return( + value=Name(id='NotImplemented', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='x', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + GeneratorExp( + elt=BinOp( + left=Name(id='x', ctx=Load()), + op=Sub(), + right=Name(id='y', ctx=Load())), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='x', ctx=Store()), + Name(id='y', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='cast', ctx=Load()), + args=[ + Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='int', ctx=Load()), + Name(id='int', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Call( + func=Name(id='zip', ctx=Load()), + args=[ + Name(id='self', ctx=Load()), + Name(id='right', ctx=Load())], + keywords=[])], + keywords=[]), + ifs=[], + is_async=0)])], + keywords=[]))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='__rsub__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load())), + arg( + arg='left', + annotation=Name(id='U', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='left', ctx=Load()), + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[])], + keywords=[])), + body=[ + Return( + value=Name(id='NotImplemented', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + GeneratorExp( + elt=BinOp( + left=Name(id='x', ctx=Load()), + op=Sub(), + right=Name(id='y', ctx=Load())), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='x', ctx=Store()), + Name(id='y', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='cast', ctx=Load()), + args=[ + Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='int', ctx=Load()), + Name(id='int', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Call( + func=Name(id='zip', ctx=Load()), + args=[ + Name(id='left', ctx=Load()), + Name(id='self', ctx=Load())], + keywords=[])], + keywords=[]), + ifs=[], + is_async=0)])], + keywords=[]))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='__mul__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load())), + arg( + arg='right', + annotation=Name(id='U', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='modulus', ctx=Store())], + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='MODULUS', + ctx=Load())), + Assign( + targets=[ + Name(id='degree', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='modulus', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='prime', ctx=Store())], + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='PRIME', + ctx=Load())), + Assign( + targets=[ + Name(id='mul', ctx=Store())], + value=BinOp( + left=List( + elts=[ + Constant(value=0)], + ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='degree', ctx=Load()), + op=Mult(), + right=Constant(value=2)))), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='degree', ctx=Load())], + keywords=[]), + body=[ + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='degree', ctx=Load())], + keywords=[]), + body=[ + AugAssign( + target=Subscript( + value=Name(id='mul', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Name(id='j', ctx=Load())), + ctx=Store()), + op=Add(), + value=BinOp( + left=Subscript( + value=Name(id='self', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + op=Mult(), + right=Subscript( + value=Name(id='right', ctx=Load()), + slice=Name(id='j', ctx=Load()), + ctx=Load())))], + orelse=[])], + orelse=[]), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='degree', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Sub(), + right=Constant(value=1)), + BinOp( + left=Name(id='degree', ctx=Load()), + op=Sub(), + right=Constant(value=1)), + UnaryOp( + op=USub(), + operand=Constant(value=1))], + keywords=[]), + body=[ + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Name(id='i', ctx=Load()), + op=Sub(), + right=Name(id='degree', ctx=Load())), + Name(id='i', ctx=Load())], + keywords=[]), + body=[ + AugAssign( + target=Subscript( + value=Name(id='mul', ctx=Load()), + slice=Name(id='j', ctx=Load()), + ctx=Store()), + op=Sub(), + value=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='mul', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + op=Mult(), + right=Subscript( + value=Name(id='modulus', ctx=Load()), + slice=BinOp( + left=Name(id='degree', ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='i', ctx=Load()), + op=Sub(), + right=Name(id='j', ctx=Load()))), + ctx=Load())), + op=Mod(), + right=Name(id='prime', ctx=Load())))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + Subscript( + value=Name(id='mul', ctx=Load()), + slice=Slice( + upper=Name(id='degree', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='__rmul__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load())), + arg( + arg='left', + annotation=Name(id='U', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__mul__', + ctx=Load()), + args=[ + Name(id='left', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='__imul__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load())), + arg( + arg='right', + annotation=Name(id='U', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__mul__', + ctx=Load()), + args=[ + Name(id='right', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='__truediv__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load())), + arg( + arg='right', + annotation=Name(id='U', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=BinOp( + left=Name(id='self', ctx=Load()), + op=Mult(), + right=Call( + func=Attribute( + value=Name(id='right', ctx=Load()), + attr='multiplicative_inverse', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='__neg__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + GeneratorExp( + elt=UnaryOp( + op=USub(), + operand=Name(id='a', ctx=Load())), + generators=[ + comprehension( + target=Name(id='a', ctx=Store()), + iter=Name(id='self', ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='scalar_mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load())), + arg( + arg='x', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply a field element by a integer. This is faster than using\n `from_int()` and field multiplication.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + GeneratorExp( + elt=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='n', ctx=Load())), + generators=[ + comprehension( + target=Name(id='n', ctx=Store()), + iter=Name(id='self', ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='deg', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n This is a support function for `multiplicative_inverse()`.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='MODULUS', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + UnaryOp( + op=USub(), + operand=Constant(value=1)), + UnaryOp( + op=USub(), + operand=Constant(value=1))], + keywords=[]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='self', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Raise( + exc=Call( + func=Name(id='ValueError', ctx=Load()), + args=[ + Constant(value='deg() does not support zero')], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='multiplicative_inverse', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the multiplicative inverse. Uses the Euclidean algorithm.\n ')), + AnnAssign( + target=Name(id='x2', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='PRIME', + ctx=Load())), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='x1', ctx=Store()), + Name(id='f1', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='list', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='MODULUS', + ctx=Load())], + keywords=[]), + BinOp( + left=List( + elts=[ + Constant(value=0)], + ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]))], + ctx=Load())), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='x2', ctx=Store()), + Name(id='f2', ctx=Store()), + Name(id='d2', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='list', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + BinOp( + left=List( + elts=[ + Constant(value=1)], + ctx=Load()), + op=Add(), + right=BinOp( + left=List( + elts=[ + Constant(value=0)], + ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)))), + Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='deg', + ctx=Load()), + args=[], + keywords=[])], + ctx=Load())), + Assign( + targets=[ + Name(id='q_0', ctx=Store())], + value=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Subscript( + value=Name(id='x2', ctx=Load()), + slice=Name(id='d2', ctx=Load()), + ctx=Load()), + UnaryOp( + op=USub(), + operand=Constant(value=1)), + Name(id='p', ctx=Load())], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='d2', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='x1', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x1', ctx=Load())], + keywords=[])), + op=Sub(), + right=Name(id='d2', ctx=Load())), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='x1', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x1', ctx=Load())], + keywords=[])), + op=Sub(), + right=Name(id='d2', ctx=Load())), + ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='q_0', ctx=Load()), + op=Mult(), + right=Subscript( + value=Name(id='x2', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()))), + op=Mod(), + right=Name(id='p', ctx=Load()))), + Assign( + targets=[ + Subscript( + value=Name(id='f1', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x1', ctx=Load())], + keywords=[])), + op=Sub(), + right=Name(id='d2', ctx=Load())), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='f1', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x1', ctx=Load())], + keywords=[])), + op=Sub(), + right=Name(id='d2', ctx=Load())), + ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='q_0', ctx=Load()), + op=Mult(), + right=Subscript( + value=Name(id='f2', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()))), + op=Mod(), + right=Name(id='p', ctx=Load())))], + orelse=[]), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='MODULUS', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + UnaryOp( + op=USub(), + operand=Constant(value=1)), + UnaryOp( + op=USub(), + operand=Constant(value=1))], + keywords=[]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='x1', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='d1', ctx=Store())], + value=Name(id='i', ctx=Load())), + Break()], + orelse=[])], + orelse=[]), + While( + test=Constant(value=True), + body=[ + If( + test=Compare( + left=Name(id='d1', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='ans', ctx=Store())], + value=Name(id='f1', ctx=Load())), + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Subscript( + value=Name(id='x1', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + UnaryOp( + op=USub(), + operand=Constant(value=1)), + Attribute( + value=Name(id='self', ctx=Load()), + attr='PRIME', + ctx=Load())], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ans', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + AugAssign( + target=Subscript( + value=Name(id='ans', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Store()), + op=Mult(), + value=Name(id='q', ctx=Load()))], + orelse=[]), + Break()], + orelse=[ + If( + test=Compare( + left=Name(id='d2', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='ans', ctx=Store())], + value=Name(id='f2', ctx=Load())), + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Subscript( + value=Name(id='x2', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + UnaryOp( + op=USub(), + operand=Constant(value=1)), + Attribute( + value=Name(id='self', ctx=Load()), + attr='PRIME', + ctx=Load())], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ans', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + AugAssign( + target=Name(id='ans', ctx=Store()), + op=Mult(), + value=Name(id='q', ctx=Load()))], + orelse=[]), + Break()], + orelse=[])]), + If( + test=Compare( + left=Name(id='d1', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='d2', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='x2', ctx=Load()), + slice=Name(id='d2', ctx=Load()), + ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Subscript( + value=Name(id='x1', ctx=Load()), + slice=Name(id='d1', ctx=Load()), + ctx=Load()), + UnaryOp( + op=USub(), + operand=Constant(value=1)), + Attribute( + value=Name(id='self', ctx=Load()), + attr='PRIME', + ctx=Load())], + keywords=[]))), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='MODULUS', + ctx=Load())], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='d2', ctx=Load()), + op=Sub(), + right=Name(id='d1', ctx=Load())))], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='x2', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='d2', ctx=Load()), + op=Sub(), + right=Name(id='d1', ctx=Load()))), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='x2', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='d2', ctx=Load()), + op=Sub(), + right=Name(id='d1', ctx=Load()))), + ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='q', ctx=Load()), + op=Mult(), + right=Subscript( + value=Name(id='x1', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()))), + op=Mod(), + right=Name(id='p', ctx=Load()))), + Assign( + targets=[ + Subscript( + value=Name(id='f2', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='d2', ctx=Load()), + op=Sub(), + right=Name(id='d1', ctx=Load()))), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='f2', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='d2', ctx=Load()), + op=Sub(), + right=Name(id='d1', ctx=Load()))), + ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='q', ctx=Load()), + op=Mult(), + right=Subscript( + value=Name(id='f1', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()))), + op=Mod(), + right=Name(id='p', ctx=Load())))], + orelse=[]), + While( + test=Compare( + left=Subscript( + value=Name(id='x2', ctx=Load()), + slice=Name(id='d2', ctx=Load()), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='d2', ctx=Store()), + op=Sub(), + value=Constant(value=1))], + orelse=[])], + orelse=[ + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='x1', ctx=Load()), + slice=Name(id='d1', ctx=Load()), + ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Subscript( + value=Name(id='x2', ctx=Load()), + slice=Name(id='d2', ctx=Load()), + ctx=Load()), + UnaryOp( + op=USub(), + operand=Constant(value=1)), + Attribute( + value=Name(id='self', ctx=Load()), + attr='PRIME', + ctx=Load())], + keywords=[]))), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='MODULUS', + ctx=Load())], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='d1', ctx=Load()), + op=Sub(), + right=Name(id='d2', ctx=Load())))], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='x1', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='d1', ctx=Load()), + op=Sub(), + right=Name(id='d2', ctx=Load()))), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='x1', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='d1', ctx=Load()), + op=Sub(), + right=Name(id='d2', ctx=Load()))), + ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='q', ctx=Load()), + op=Mult(), + right=Subscript( + value=Name(id='x2', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()))), + op=Mod(), + right=Name(id='p', ctx=Load()))), + Assign( + targets=[ + Subscript( + value=Name(id='f1', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='d1', ctx=Load()), + op=Sub(), + right=Name(id='d2', ctx=Load()))), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Subscript( + value=Name(id='f1', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='d1', ctx=Load()), + op=Sub(), + right=Name(id='d2', ctx=Load()))), + ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='q', ctx=Load()), + op=Mult(), + right=Subscript( + value=Name(id='f2', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()))), + op=Mod(), + right=Name(id='p', ctx=Load())))], + orelse=[]), + While( + test=Compare( + left=Subscript( + value=Name(id='x1', ctx=Load()), + slice=Name(id='d1', ctx=Load()), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='d1', ctx=Store()), + op=Sub(), + value=Constant(value=1))], + orelse=[])])], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + Name(id='ans', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='__pow__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load())), + arg( + arg='exponent', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='degree', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='MODULUS', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='exponent', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='self', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='multiplicative_inverse', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='exponent', ctx=Load())))], + orelse=[]), + Assign( + targets=[ + Name(id='res', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + BinOp( + left=List( + elts=[ + Constant(value=1)], + ctx=Load()), + op=Add(), + right=BinOp( + left=List( + elts=[ + Constant(value=0)], + ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='degree', ctx=Load()), + op=Sub(), + right=Constant(value=1))))], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Name(id='self', ctx=Load())), + While( + test=Compare( + left=Name(id='exponent', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + If( + test=Compare( + left=BinOp( + left=Name(id='exponent', ctx=Load()), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + AugAssign( + target=Name(id='res', ctx=Store()), + op=Mult(), + value=Name(id='s', ctx=Load()))], + orelse=[]), + AugAssign( + target=Name(id='s', ctx=Store()), + op=Mult(), + value=Name(id='s', ctx=Load())), + AugAssign( + target=Name(id='exponent', ctx=Store()), + op=FloorDiv(), + value=Constant(value=2))], + orelse=[]), + Return( + value=Name(id='res', ctx=Load()))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='__ipow__', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load())), + arg( + arg='right', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='__pow__', + ctx=Load()), + args=[ + Name(id='right', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='calculate_frobenius_coefficients', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='U', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the coefficients needed by `frobenius()`.\n ')), + Assign( + targets=[ + Name(id='coefficients', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='cls', ctx=Load()), + attr='MODULUS', + ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=BinOp( + left=List( + elts=[ + Constant(value=0)], + ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='cls', ctx=Load()), + attr='MODULUS', + ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Store())], + value=Constant(value=1)), + Expr( + value=Call( + func=Attribute( + value=Name(id='coefficients', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Attribute( + value=Name(id='cls', ctx=Load()), + attr='__new__', + ctx=Load()), + args=[ + Name(id='cls', ctx=Load()), + Name(id='x', ctx=Load())], + keywords=[]), + op=Pow(), + right=Attribute( + value=Name(id='cls', ctx=Load()), + attr='PRIME', + ctx=Load()))], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='coefficients', ctx=Load())], + keywords=[]))], + decorator_list=[ + Name(id='classmethod', ctx=Load())], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='frobenius', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='self', + annotation=Name(id='U', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns `self ** p`. This function is known as the Frobenius\n endomorphism and has many special mathematical properties. In\n particular it is extremely cheap to compute compared to other\n exponentiations.\n ')), + Assign( + targets=[ + Name(id='ans', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + AnnAssign( + target=Name(id='a', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='a', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + body=[ + AugAssign( + target=Name(id='ans', ctx=Store()), + op=Add(), + value=Call( + func=Attribute( + value=Call( + func=Name(id='cast', ctx=Load()), + args=[ + Name(id='U', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='FROBENIUS_COEFFICIENTS', + ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())], + keywords=[]), + attr='scalar_mul', + ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='ans', ctx=Load()))], + decorator_list=[], + returns=Name(id='U', ctx=Load()))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/crypto/finite_field.v b/coq/ethereum/crypto/finite_field.v new file mode 100644 index 0000000000..512b797838 --- /dev/null +++ b/coq/ethereum/crypto/finite_field.v @@ -0,0 +1,9 @@ +(* Generated *) +(* +Finite Fields +^^^^^^^^^^^^^ +*) + +Require typing. +Require ethereum_types.bytes. +Require typing_extensions. diff --git a/coq/ethereum/crypto/hash.ast b/coq/ethereum/crypto/hash.ast new file mode 100644 index 0000000000..0f8bc53736 --- /dev/null +++ b/coq/ethereum/crypto/hash.ast @@ -0,0 +1,121 @@ +Module( + body=[ + Expr( + value=Constant(value='\nCryptographic Hash Functions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nCryptographic hashing functions.\n')), + ImportFrom( + module='Crypto.Hash', + names=[ + alias(name='keccak')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes32'), + alias(name='Bytes64')], + level=0), + Assign( + targets=[ + Name(id='Hash32', ctx=Store())], + value=Name(id='Bytes32', ctx=Load())), + Assign( + targets=[ + Name(id='Hash64', ctx=Store())], + value=Name(id='Bytes64', ctx=Load())), + FunctionDef( + name='keccak256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes the keccak256 hash of the input `buffer`.\n\n Parameters\n ----------\n buffer :\n Input for the hashing function.\n\n Returns\n -------\n hash : `ethereum.base_types.Hash32`\n Output of the hash function.\n ')), + Assign( + targets=[ + Name(id='k', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='keccak', ctx=Load()), + attr='new', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='digest_bits', + value=Constant(value=256))])), + Return( + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='k', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Name(id='buffer', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='keccak512', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes the keccak512 hash of the input `buffer`.\n\n Parameters\n ----------\n buffer :\n Input for the hashing function.\n\n Returns\n -------\n hash : `ethereum.base_types.Hash32`\n Output of the hash function.\n ')), + Assign( + targets=[ + Name(id='k', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='keccak', ctx=Load()), + attr='new', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='digest_bits', + value=Constant(value=512))])), + Return( + value=Call( + func=Name(id='Hash64', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='k', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Name(id='buffer', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash64', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/crypto/hash.v b/coq/ethereum/crypto/hash.v new file mode 100644 index 0000000000..3bf38bb95b --- /dev/null +++ b/coq/ethereum/crypto/hash.v @@ -0,0 +1,61 @@ +(* Generated *) +(* +Cryptographic Hash Functions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Cryptographic hashing functions. +*) + +Require Crypto.Hash. +Require ethereum_types.bytes. + +Definition keccak256 (buffer : Bytes) : M Hash32 := + (* + Computes the keccak256 hash of the input `buffer`. + + Parameters + ---------- + buffer : + Input for the hashing function. + + Returns + ------- + hash : `ethereum.base_types.Hash32` + Output of the hash function. + *) + do* M.assign "k" [[ + M.get_field ~(| Crypto.Hash.keccak, "new" |) ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition keccak512 (buffer : Bytes) : M Hash64 := + (* + Computes the keccak512 hash of the input `buffer`. + + Parameters + ---------- + buffer : + Input for the hashing function. + + Returns + ------- + hash : `ethereum.base_types.Hash32` + Output of the hash function. + *) + do* M.assign "k" [[ + M.get_field ~(| Crypto.Hash.keccak, "new" |) ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/crypto/kzg.ast b/coq/ethereum/crypto/kzg.ast new file mode 100644 index 0000000000..97ef646f13 --- /dev/null +++ b/coq/ethereum/crypto/kzg.ast @@ -0,0 +1,696 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe KZG Implementation\n^^^^^^^^^^^^^^^^^^^^^^\n')), + ImportFrom( + module='hashlib', + names=[ + alias(name='sha256')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='eth_typing.bls', + names=[ + alias(name='BLSPubkey'), + alias(name='BLSSignature')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes32'), + alias(name='Bytes48'), + alias(name='Bytes96')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='py_ecc.bls', + names=[ + alias(name='G2ProofOfPossession')], + level=0), + ImportFrom( + module='py_ecc.bls.g2_primitives', + names=[ + alias(name='pubkey_to_G1'), + alias(name='signature_to_G2')], + level=0), + ImportFrom( + module='py_ecc.fields', + names=[ + alias(name='optimized_bls12_381_FQ'), + alias(name='optimized_bls12_381_FQ2')], + level=0), + ImportFrom( + module='py_ecc.fields', + names=[ + alias(name='optimized_bls12_381_FQ12', asname='FQ12')], + level=0), + ImportFrom( + module='py_ecc.optimized_bls12_381', + names=[ + alias(name='add'), + alias(name='multiply'), + alias(name='neg')], + level=0), + ImportFrom( + module='py_ecc.optimized_bls12_381.optimized_curve', + names=[ + alias(name='G1'), + alias(name='G2')], + level=0), + ImportFrom( + module='py_ecc.optimized_bls12_381.optimized_pairing', + names=[ + alias(name='final_exponentiate'), + alias(name='pairing')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + Assign( + targets=[ + Name(id='FQ', ctx=Store())], + value=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='optimized_bls12_381_FQ', ctx=Load()), + Name(id='optimized_bls12_381_FQ', ctx=Load()), + Name(id='optimized_bls12_381_FQ', ctx=Load())], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='FQ2', ctx=Store())], + value=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='optimized_bls12_381_FQ2', ctx=Load()), + Name(id='optimized_bls12_381_FQ2', ctx=Load()), + Name(id='optimized_bls12_381_FQ2', ctx=Load())], + ctx=Load()), + ctx=Load())), + ClassDef( + name='KZGCommitment', + bases=[ + Name(id='Bytes48', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='KZG commitment to a polynomial.')), + Pass()], + decorator_list=[]), + ClassDef( + name='KZGProof', + bases=[ + Name(id='Bytes48', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='KZG proof')), + Pass()], + decorator_list=[]), + ClassDef( + name='BLSFieldElement', + bases=[ + Name(id='U256', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='A field element in the BLS12-381 field.')), + Pass()], + decorator_list=[]), + ClassDef( + name='VersionedHash', + bases=[ + Name(id='Bytes32', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='A versioned hash.')), + Pass()], + decorator_list=[]), + ClassDef( + name='G2Point', + bases=[ + Name(id='Bytes96', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='A point in G2.')), + Pass()], + decorator_list=[]), + Assign( + targets=[ + Name(id='VERSIONED_HASH_VERSION_KZG', ctx=Store())], + value=Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='BYTES_PER_COMMITMENT', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BYTES_PER_PROOF', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BYTES_PER_FIELD_ELEMENT', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='G1_POINT_AT_INFINITY', ctx=Store())], + value=BinOp( + left=Constant(value=b'\xc0'), + op=Add(), + right=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=47)))), + Assign( + targets=[ + Name(id='BLS_MODULUS', ctx=Store())], + value=Call( + func=Name(id='BLSFieldElement', ctx=Load()), + args=[ + Constant(value=52435875175126190479447740508185965837690552500527637822603658699938581184513)], + keywords=[])), + Assign( + targets=[ + Name(id='KZG_SETUP_G2_LENGTH', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='KZG_SETUP_G2_MONOMIAL_1', ctx=Store())], + value=Constant(value='0xb5bfd7dd8cdeb128843bc287230af38926187075cbfbefa81009a2ce615ac53d2914e5870cb452d2afaaab24f3499f72185cbfee53492714734429b7b38608e23926c911cceceac9a36851477ba4c60b087041de621000edc98edada20c1def2')), + FunctionDef( + name='kzg_commitment_to_versioned_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='kzg_commitment', + annotation=Name(id='KZGCommitment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a KZG commitment to a versioned hash.\n ')), + Return( + value=Call( + func=Name(id='VersionedHash', ctx=Load()), + args=[ + BinOp( + left=Name(id='VERSIONED_HASH_VERSION_KZG', ctx=Load()), + op=Add(), + right=Subscript( + value=Call( + func=Name(id='Bytes32', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='sha256', ctx=Load()), + args=[ + Name(id='kzg_commitment', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + slice=Slice( + lower=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='VersionedHash', ctx=Load())), + FunctionDef( + name='validate_kzg_g1', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='b', + annotation=Name(id='Bytes48', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform BLS validation required by the types `KZGProof`\n and `KZGCommitment`.\n ')), + If( + test=Compare( + left=Name(id='b', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='G1_POINT_AT_INFINITY', ctx=Load())]), + body=[ + Return()], + orelse=[]), + Assert( + test=Call( + func=Attribute( + value=Name(id='G2ProofOfPossession', ctx=Load()), + attr='KeyValidate', + ctx=Load()), + args=[ + Call( + func=Name(id='BLSPubkey', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bytes_to_kzg_commitment', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='b', + annotation=Name(id='Bytes48', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert untrusted bytes into a trusted and validated KZGCommitment.\n ')), + Expr( + value=Call( + func=Name(id='validate_kzg_g1', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='KZGCommitment', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='KZGCommitment', ctx=Load())), + FunctionDef( + name='bytes_to_bls_field', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='b', + annotation=Name(id='Bytes32', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert untrusted bytes to a trusted and validated BLS scalar\n field element. This function does not accept inputs greater than\n the BLS modulus.\n ')), + Assign( + targets=[ + Name(id='field_element', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='int', ctx=Load()), + attr='from_bytes', + ctx=Load()), + args=[ + Name(id='b', ctx=Load()), + Constant(value='big')], + keywords=[])), + Assert( + test=Compare( + left=Name(id='field_element', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='BLS_MODULUS', ctx=Load())], + keywords=[])])), + Return( + value=Call( + func=Name(id='BLSFieldElement', ctx=Load()), + args=[ + Name(id='field_element', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='BLSFieldElement', ctx=Load())), + FunctionDef( + name='bytes_to_kzg_proof', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='b', + annotation=Name(id='Bytes48', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert untrusted bytes into a trusted and validated KZGProof.\n ')), + Expr( + value=Call( + func=Name(id='validate_kzg_g1', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='KZGProof', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='KZGProof', ctx=Load())), + FunctionDef( + name='pairing_check', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='values', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='FQ', ctx=Load()), + Name(id='FQ2', ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='FQ', ctx=Load()), + Name(id='FQ2', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the pairings are valid.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='p_q_1', ctx=Store()), + Name(id='p_q_2', ctx=Store())], + ctx=Store())], + value=Name(id='values', ctx=Load())), + Assign( + targets=[ + Name(id='final_exponentiation', ctx=Store())], + value=Call( + func=Name(id='final_exponentiate', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='pairing', ctx=Load()), + args=[ + Subscript( + value=Name(id='p_q_1', ctx=Load()), + slice=Constant(value=1), + ctx=Load()), + Subscript( + value=Name(id='p_q_1', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[ + keyword( + arg='final_exponentiate', + value=Constant(value=False))]), + op=Mult(), + right=Call( + func=Name(id='pairing', ctx=Load()), + args=[ + Subscript( + value=Name(id='p_q_2', ctx=Load()), + slice=Constant(value=1), + ctx=Load()), + Subscript( + value=Name(id='p_q_2', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[ + keyword( + arg='final_exponentiate', + value=Constant(value=False))]))], + keywords=[])), + Return( + value=Compare( + left=Name(id='final_exponentiation', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='FQ12', ctx=Load()), + attr='one', + ctx=Load()), + args=[], + keywords=[])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='verify_kzg_proof', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='commitment_bytes', + annotation=Name(id='Bytes48', ctx=Load())), + arg( + arg='z_bytes', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='y_bytes', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='proof_bytes', + annotation=Name(id='Bytes48', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Verify KZG proof that ``p(z) == y`` where ``p(z)``\n is the polynomial represented by ``polynomial_kzg``.\n Receives inputs as bytes.\n Public method.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='commitment_bytes', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='BYTES_PER_COMMITMENT', ctx=Load())])), + Assert( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='z_bytes', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='BYTES_PER_FIELD_ELEMENT', ctx=Load())])), + Assert( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='y_bytes', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='BYTES_PER_FIELD_ELEMENT', ctx=Load())])), + Assert( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='proof_bytes', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='BYTES_PER_PROOF', ctx=Load())])), + Return( + value=Call( + func=Name(id='verify_kzg_proof_impl', ctx=Load()), + args=[ + Call( + func=Name(id='bytes_to_kzg_commitment', ctx=Load()), + args=[ + Name(id='commitment_bytes', ctx=Load())], + keywords=[]), + Call( + func=Name(id='bytes_to_bls_field', ctx=Load()), + args=[ + Name(id='z_bytes', ctx=Load())], + keywords=[]), + Call( + func=Name(id='bytes_to_bls_field', ctx=Load()), + args=[ + Name(id='y_bytes', ctx=Load())], + keywords=[]), + Call( + func=Name(id='bytes_to_kzg_proof', ctx=Load()), + args=[ + Name(id='proof_bytes', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='verify_kzg_proof_impl', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='commitment', + annotation=Name(id='KZGCommitment', ctx=Load())), + arg( + arg='z', + annotation=Name(id='BLSFieldElement', ctx=Load())), + arg( + arg='y', + annotation=Name(id='BLSFieldElement', ctx=Load())), + arg( + arg='proof', + annotation=Name(id='KZGProof', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Verify KZG proof that ``p(z) == y`` where ``p(z)``\n is the polynomial represented by ``polynomial_kzg``.\n ')), + Assign( + targets=[ + Name(id='X_minus_z', ctx=Store())], + value=Call( + func=Name(id='add', ctx=Load()), + args=[ + Call( + func=Name(id='signature_to_G2', ctx=Load()), + args=[ + Call( + func=Name(id='BLSSignature', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Name(id='KZG_SETUP_G2_MONOMIAL_1', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + Call( + func=Name(id='multiply', ctx=Load()), + args=[ + Name(id='G2', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='BLS_MODULUS', ctx=Load()), + op=Sub(), + right=Name(id='z', ctx=Load())), + op=Mod(), + right=Name(id='BLS_MODULUS', ctx=Load()))], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='P_minus_y', ctx=Store())], + value=Call( + func=Name(id='add', ctx=Load()), + args=[ + Call( + func=Name(id='pubkey_to_G1', ctx=Load()), + args=[ + Call( + func=Name(id='BLSPubkey', ctx=Load()), + args=[ + Name(id='commitment', ctx=Load())], + keywords=[])], + keywords=[]), + Call( + func=Name(id='multiply', ctx=Load()), + args=[ + Name(id='G1', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='BLS_MODULUS', ctx=Load()), + op=Sub(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='BLS_MODULUS', ctx=Load()))], + keywords=[])], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='pairing_check', ctx=Load()), + args=[ + Tuple( + elts=[ + Tuple( + elts=[ + Name(id='P_minus_y', ctx=Load()), + Call( + func=Name(id='neg', ctx=Load()), + args=[ + Name(id='G2', ctx=Load())], + keywords=[])], + ctx=Load()), + Tuple( + elts=[ + Call( + func=Name(id='pubkey_to_G1', ctx=Load()), + args=[ + Call( + func=Name(id='BLSPubkey', ctx=Load()), + args=[ + Name(id='proof', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='X_minus_z', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/crypto/kzg.v b/coq/ethereum/crypto/kzg.v new file mode 100644 index 0000000000..6c83228f1d --- /dev/null +++ b/coq/ethereum/crypto/kzg.v @@ -0,0 +1,138 @@ +(* Generated *) +(* +The KZG Implementation +^^^^^^^^^^^^^^^^^^^^^^ +*) + +Require hashlib. +Require typing. +Require eth_typing.bls. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require py_ecc.bls. +Require py_ecc.bls.g2_primitives. +Require py_ecc.fields. +Require py_ecc.fields. +Require py_ecc.optimized_bls12_381. +Require py_ecc.optimized_bls12_381.optimized_curve. +Require py_ecc.optimized_bls12_381.optimized_pairing. +Require ethereum.utils.hexadecimal. + +Definition kzg_commitment_to_versioned_hash (kzg_commitment : KZGCommitment) : M VersionedHash := + (* + Convert a KZG commitment to a versioned hash. + *) + (* TODO statement *) + M.pure tt. + +Definition validate_kzg_g1 (b : Bytes48) : M unit := + (* + Perform BLS validation required by the types `KZGProof` + and `KZGCommitment`. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_kzg_commitment (b : Bytes48) : M KZGCommitment := + (* + Convert untrusted bytes into a trusted and validated KZGCommitment. + *) + do* [[ M.get_local ~(| "validate_kzg_g1" |) ~(| + b + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition bytes_to_bls_field (b : Bytes32) : M BLSFieldElement := + (* + Convert untrusted bytes to a trusted and validated BLS scalar + field element. This function does not accept inputs greater than + the BLS modulus. + *) + do* M.assign "field_element" [[ + M.get_field ~(| M.get_local ~(| "int" |), "from_bytes" |) ~(| + b, + (* TODO constant *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_kzg_proof (b : Bytes48) : M KZGProof := + (* + Convert untrusted bytes into a trusted and validated KZGProof. + *) + do* [[ M.get_local ~(| "validate_kzg_g1" |) ~(| + b + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition pairing_check (values : (* TODO type *)) : M bool := + (* + Check if the pairings are valid. + *) + (* TODO assignment *) + do* M.assign "final_exponentiation" [[ + py_ecc.optimized_bls12_381.optimized_pairing.final_exponentiate ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition verify_kzg_proof (commitment_bytes : Bytes48) (z_bytes : Bytes32) (y_bytes : Bytes32) (proof_bytes : Bytes48) : M bool := + (* + Verify KZG proof that ``p(z) == y`` where ``p(z)`` + is the polynomial represented by ``polynomial_kzg``. + Receives inputs as bytes. + Public method. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition verify_kzg_proof_impl (commitment : KZGCommitment) (z : BLSFieldElement) (y : BLSFieldElement) (proof : KZGProof) : M bool := + (* + Verify KZG proof that ``p(z) == y`` where ``p(z)`` + is the polynomial represented by ``polynomial_kzg``. + *) + do* M.assign "X_minus_z" [[ + py_ecc.optimized_bls12_381.add ~(| + py_ecc.bls.g2_primitives.signature_to_G2 ~(| + eth_typing.bls.BLSSignature ~(| + ethereum.utils.hexadecimal.hex_to_bytes ~(| + M.get_local ~(| "KZG_SETUP_G2_MONOMIAL_1" |) + |) + |) + |), + py_ecc.optimized_bls12_381.multiply ~(| + py_ecc.optimized_bls12_381.optimized_curve.G2, + M.get_local ~(| "int" |) ~(| + (* TODO expression *) + |) + |) + |) in + ]] in + do* M.assign "P_minus_y" [[ + py_ecc.optimized_bls12_381.add ~(| + py_ecc.bls.g2_primitives.pubkey_to_G1 ~(| + eth_typing.bls.BLSPubkey ~(| + commitment + |) + |), + py_ecc.optimized_bls12_381.multiply ~(| + py_ecc.optimized_bls12_381.optimized_curve.G1, + M.get_local ~(| "int" |) ~(| + (* TODO expression *) + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/__init__.ast b/coq/ethereum/dao_fork/__init__.ast new file mode 100644 index 0000000000..d514928cd0 --- /dev/null +++ b/coq/ethereum/dao_fork/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe DAO Fork is a response to a smart contract exploit known as the 2016 DAO\nAttack where a vulnerable contract was drained of its ether. This fork recovers\nthe stolen funds into a new contract.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=1920000)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/__init__.v b/coq/ethereum/dao_fork/__init__.v new file mode 100644 index 0000000000..ad990a2598 --- /dev/null +++ b/coq/ethereum/dao_fork/__init__.v @@ -0,0 +1,8 @@ +(* Generated *) +(* +The DAO Fork is a response to a smart contract exploit known as the 2016 DAO +Attack where a vulnerable contract was drained of its ether. This fork recovers +the stolen funds into a new contract. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/dao_fork/blocks.ast b/coq/ethereum/dao_fork/blocks.ast new file mode 100644 index 0000000000..dce2db5da0 --- /dev/null +++ b/coq/ethereum/dao_fork/blocks.ast @@ -0,0 +1,218 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mix_digest', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='post_state', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/blocks.v b/coq/ethereum/dao_fork/blocks.v new file mode 100644 index 0000000000..7a2d0dd965 --- /dev/null +++ b/coq/ethereum/dao_fork/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.dao_fork.fork_types. +Require ethereum.dao_fork.transactions. diff --git a/coq/ethereum/dao_fork/bloom.ast b/coq/ethereum/dao_fork/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/dao_fork/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/bloom.v b/coq/ethereum/dao_fork/bloom.v new file mode 100644 index 0000000000..4700caa011 --- /dev/null +++ b/coq/ethereum/dao_fork/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.dao_fork.blocks. +Require ethereum.dao_fork.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/dao.ast b/coq/ethereum/dao_fork/dao.ast new file mode 100644 index 0000000000..5ba43ace6d --- /dev/null +++ b/coq/ethereum/dao_fork/dao.ast @@ -0,0 +1,200 @@ +Module( + body=[ + Expr( + value=Constant(value='\nDao Fork\n^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe Dao Fork was an irregular state change that moved all Ether from a large\ncollection of accounts (The Dao and all its children) to a recovery contract.\n\nThe recovery contract was previously created using normal contract deployment.\n')), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='get_account'), + alias(name='move_ether')], + level=1), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=1), + Assign( + targets=[ + Name(id='DAO_ACCOUNTS', ctx=Store())], + value=ListComp( + elt=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='address', ctx=Store()), + iter=List( + elts=[ + Constant(value='0xd4fe7bc31cedb7bfb8a345f31e668033056b2728'), + Constant(value='0xb3fb0e5aba0e20e5c49d252dfd30e102b171a425'), + Constant(value='0x2c19c7f9ae8b751e37aeb2d93a699722395ae18f'), + Constant(value='0xecd135fa4f61a655311e86238c92adcd779555d2'), + Constant(value='0x1975bd06d486162d5dc297798dfc41edd5d160a7'), + Constant(value='0xa3acf3a1e16b1d7c315e23510fdd7847b48234f6'), + Constant(value='0x319f70bab6845585f412ec7724b744fec6095c85'), + Constant(value='0x06706dd3f2c9abf0a21ddcc6941d9b86f0596936'), + Constant(value='0x5c8536898fbb74fc7445814902fd08422eac56d0'), + Constant(value='0x6966ab0d485353095148a2155858910e0965b6f9'), + Constant(value='0x779543a0491a837ca36ce8c635d6154e3c4911a6'), + Constant(value='0x2a5ed960395e2a49b1c758cef4aa15213cfd874c'), + Constant(value='0x5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5'), + Constant(value='0x9c50426be05db97f5d64fc54bf89eff947f0a321'), + Constant(value='0x200450f06520bdd6c527622a273333384d870efb'), + Constant(value='0xbe8539bfe837b67d1282b2b1d61c3f723966f049'), + Constant(value='0x6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb'), + Constant(value='0xf1385fb24aad0cd7432824085e42aff90886fef5'), + Constant(value='0xd1ac8b1ef1b69ff51d1d401a476e7e612414f091'), + Constant(value='0x8163e7fb499e90f8544ea62bbf80d21cd26d9efd'), + Constant(value='0x51e0ddd9998364a2eb38588679f0d2c42653e4a6'), + Constant(value='0x627a0a960c079c21c34f7612d5d230e01b4ad4c7'), + Constant(value='0xf0b1aa0eb660754448a7937c022e30aa692fe0c5'), + Constant(value='0x24c4d950dfd4dd1902bbed3508144a54542bba94'), + Constant(value='0x9f27daea7aca0aa0446220b98d028715e3bc803d'), + Constant(value='0xa5dc5acd6a7968a4554d89d65e59b7fd3bff0f90'), + Constant(value='0xd9aef3a1e38a39c16b31d1ace71bca8ef58d315b'), + Constant(value='0x63ed5a272de2f6d968408b4acb9024f4cc208ebf'), + Constant(value='0x6f6704e5a10332af6672e50b3d9754dc460dfa4d'), + Constant(value='0x77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6'), + Constant(value='0x492ea3bb0f3315521c31f273e565b868fc090f17'), + Constant(value='0x0ff30d6de14a8224aa97b78aea5388d1c51c1f00'), + Constant(value='0x9ea779f907f0b315b364b0cfc39a0fde5b02a416'), + Constant(value='0xceaeb481747ca6c540a000c1f3641f8cef161fa7'), + Constant(value='0xcc34673c6c40e791051898567a1222daf90be287'), + Constant(value='0x579a80d909f346fbfb1189493f521d7f48d52238'), + Constant(value='0xe308bd1ac5fda103967359b2712dd89deffb7973'), + Constant(value='0x4cb31628079fb14e4bc3cd5e30c2f7489b00960c'), + Constant(value='0xac1ecab32727358dba8962a0f3b261731aad9723'), + Constant(value='0x4fd6ace747f06ece9c49699c7cabc62d02211f75'), + Constant(value='0x440c59b325d2997a134c2c7c60a8c61611212bad'), + Constant(value='0x4486a3d68fac6967006d7a517b889fd3f98c102b'), + Constant(value='0x9c15b54878ba618f494b38f0ae7443db6af648ba'), + Constant(value='0x27b137a85656544b1ccb5a0f2e561a5703c6a68f'), + Constant(value='0x21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241'), + Constant(value='0x23b75c2f6791eef49c69684db4c6c1f93bf49a50'), + Constant(value='0x1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b'), + Constant(value='0xb9637156d330c0d605a791f1c31ba5890582fe1c'), + Constant(value='0x6131c42fa982e56929107413a9d526fd99405560'), + Constant(value='0x1591fc0f688c81fbeb17f5426a162a7024d430c2'), + Constant(value='0x542a9515200d14b68e934e9830d91645a980dd7a'), + Constant(value='0xc4bbd073882dd2add2424cf47d35213405b01324'), + Constant(value='0x782495b7b3355efb2833d56ecb34dc22ad7dfcc4'), + Constant(value='0x58b95c9a9d5d26825e70a82b6adb139d3fd829eb'), + Constant(value='0x3ba4d81db016dc2890c81f3acec2454bff5aada5'), + Constant(value='0xb52042c8ca3f8aa246fa79c3feaa3d959347c0ab'), + Constant(value='0xe4ae1efdfc53b73893af49113d8694a057b9c0d1'), + Constant(value='0x3c02a7bc0391e86d91b7d144e61c2c01a25a79c5'), + Constant(value='0x0737a6b837f97f46ebade41b9bc3e1c509c85c53'), + Constant(value='0x97f43a37f595ab5dd318fb46e7a155eae057317a'), + Constant(value='0x52c5317c848ba20c7504cb2c8052abd1fde29d03'), + Constant(value='0x4863226780fe7c0356454236d3b1c8792785748d'), + Constant(value='0x5d2b2e6fcbe3b11d26b525e085ff818dae332479'), + Constant(value='0x5f9f3392e9f62f63b8eac0beb55541fc8627f42c'), + Constant(value='0x057b56736d32b86616a10f619859c6cd6f59092a'), + Constant(value='0x9aa008f65de0b923a2a4f02012ad034a5e2e2192'), + Constant(value='0x304a554a310c7e546dfe434669c62820b7d83490'), + Constant(value='0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79'), + Constant(value='0x4deb0033bb26bc534b197e61d19e0733e5679784'), + Constant(value='0x07f5c1e1bc2c93e0402f23341973a0e043f7bf8a'), + Constant(value='0x35a051a0010aba705c9008d7a7eff6fb88f6ea7b'), + Constant(value='0x4fa802324e929786dbda3b8820dc7834e9134a2a'), + Constant(value='0x9da397b9e80755301a3b32173283a91c0ef6c87e'), + Constant(value='0x8d9edb3054ce5c5774a420ac37ebae0ac02343c6'), + Constant(value='0x0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9'), + Constant(value='0x5dc28b15dffed94048d73806ce4b7a4612a1d48f'), + Constant(value='0xbcf899e6c7d9d5a215ab1e3444c86806fa854c76'), + Constant(value='0x12e626b0eebfe86a56d633b9864e389b45dcb260'), + Constant(value='0xa2f1ccba9395d7fcb155bba8bc92db9bafaeade7'), + Constant(value='0xec8e57756626fdc07c63ad2eafbd28d08e7b0ca5'), + Constant(value='0xd164b088bd9108b60d0ca3751da4bceb207b0782'), + Constant(value='0x6231b6d0d5e77fe001c2a460bd9584fee60d409b'), + Constant(value='0x1cba23d343a983e9b5cfd19496b9a9701ada385f'), + Constant(value='0xa82f360a8d3455c5c41366975bde739c37bfeb8a'), + Constant(value='0x9fcd2deaff372a39cc679d5c5e4de7bafb0b1339'), + Constant(value='0x005f5cee7a43331d5a3d3eec71305925a62f34b6'), + Constant(value='0x0e0da70933f4c7849fc0d203f5d1d43b9ae4532d'), + Constant(value='0xd131637d5275fd1a68a3200f4ad25c71a2a9522e'), + Constant(value='0xbc07118b9ac290e4622f5e77a0853539789effbe'), + Constant(value='0x47e7aa56d6bdf3f36be34619660de61275420af8'), + Constant(value='0xacd87e28b0c9d1254e868b81cba4cc20d9a32225'), + Constant(value='0xadf80daec7ba8dcf15392f1ac611fff65d94f880'), + Constant(value='0x5524c55fb03cf21f549444ccbecb664d0acad706'), + Constant(value='0x40b803a9abce16f50f36a77ba41180eb90023925'), + Constant(value='0xfe24cdd8648121a43a7c86d289be4dd2951ed49f'), + Constant(value='0x17802f43a0137c506ba92291391a8a8f207f487d'), + Constant(value='0x253488078a4edf4d6f42f113d1e62836a942cf1a'), + Constant(value='0x86af3e9626fce1957c82e88cbf04ddf3a2ed7915'), + Constant(value='0xb136707642a4ea12fb4bae820f03d2562ebff487'), + Constant(value='0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940'), + Constant(value='0xf14c14075d6c4ed84b86798af0956deef67365b5'), + Constant(value='0xca544e5c4687d109611d0f8f928b53a25af72448'), + Constant(value='0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c'), + Constant(value='0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7'), + Constant(value='0x6d87578288b6cb5549d5076a207456a1f6a63dc0'), + Constant(value='0xb2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e'), + Constant(value='0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6'), + Constant(value='0x2b3455ec7fedf16e646268bf88846bd7a2319bb2'), + Constant(value='0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a'), + Constant(value='0xd343b217de44030afaa275f54d31a9317c7f441e'), + Constant(value='0x84ef4b2357079cd7a7c69fd7a37cd0609a679106'), + Constant(value='0xda2fef9e4a3230988ff17df2165440f37e8b1708'), + Constant(value='0xf4c64518ea10f995918a454158c6b61407ea345c'), + Constant(value='0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97'), + Constant(value='0xbb9bc244d798123fde783fcc1c72d3bb8c189413'), + Constant(value='0x807640a13483f8ac783c557fcdf27be11ea4ac7a')], + ctx=Load()), + ifs=[], + is_async=0)])), + Assign( + targets=[ + Name(id='DAO_RECOVERY', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0xbf4ed7b27f1d666546e30d74d50d173d20bca754')], + keywords=[])), + FunctionDef( + name='apply_dao', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Apply the dao fork to the state.\n\n Parameters\n ----------\n state :\n State before applying the DAO Fork.\n ')), + For( + target=Name(id='address', ctx=Store()), + iter=Name(id='DAO_ACCOUNTS', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='DAO_RECOVERY', ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/dao.v b/coq/ethereum/dao_fork/dao.v new file mode 100644 index 0000000000..25bfae2721 --- /dev/null +++ b/coq/ethereum/dao_fork/dao.v @@ -0,0 +1,32 @@ +(* Generated *) +(* +Dao Fork +^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The Dao Fork was an irregular state change that moved all Ether from a large +collection of accounts (The Dao and all its children) to a recovery contract. + +The recovery contract was previously created using normal contract deployment. +*) + +Require ethereum.dao_fork.state. +Require ethereum.dao_fork.utils.hexadecimal. + +Definition apply_dao (state : State) : M unit := + (* + Apply the dao fork to the state. + + Parameters + ---------- + state : + State before applying the DAO Fork. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/fork.ast b/coq/ethereum/dao_fork/fork.ast new file mode 100644 index 0000000000..68fa9d77d2 --- /dev/null +++ b/coq/ethereum/dao_fork/fork.ast @@ -0,0 +1,2974 @@ +Module( + body=[ + Expr( + value=Constant(value='\n.. _dao-fork:\n\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.ethash', + names=[ + alias(name='dataset_size'), + alias(name='generate_cache'), + alias(name='hashimoto_light')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='FORK_CRITERIA'), + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='dao', + names=[ + alias(name='apply_dao')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='create_ether'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='Transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BLOCK_REWARD', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=5), + op=Mult(), + right=BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=18)))], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=131072)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_OMMER_DEPTH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity.\n\n The DAO-Fork occurred as a result of the `2016 DAO Hacks\n `_ in which an\n unknown entity managed to drain more than 3.6 million ether causing the\n price of ether to drop by nearly 35%. This fork was the solution to the\n hacks and manually reset the affected parties' accounts to their state\n prior to the attack. This fork essentially rewrote the history of the\n Ethereum network.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ")), + Expr( + value=Call( + func=Name(id='apply_dao', ctx=Load()), + args=[ + Attribute( + value=Name(id='old', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='validate_ommers', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='chain', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_difficulty', ctx=Store())], + value=Call( + func=Name(id='calculate_block_difficulty', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_difficulty', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='FORK_CRITERIA', ctx=Load()), + attr='block_number', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='FORK_CRITERIA', ctx=Load()), + attr='block_number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[]))])]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'dao-hard-fork')]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='validate_proof_of_work', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generate_header_hash_for_pow', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate rlp hash of the header which is to be used for Proof-of-Work\n verification.\n\n In other words, the PoW artefacts `mix_digest` and `nonce` are ignored\n while calculating this hash.\n\n A particular PoW is valid for a single hash, that hash is computed by\n this function. The `nonce` and `mix_digest` are omitted from this hash\n because they are being changed by miners in their search for a sufficient\n proof-of-work.\n\n Parameters\n ----------\n header :\n The header object for which the hash is to be generated.\n\n Returns\n -------\n hash : `Hash32`\n The PoW valid rlp hash of the passed in header.\n ')), + Assign( + targets=[ + Name(id='header_data_without_pow_artefacts', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='state_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='transactions_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='receipt_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='bloom', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='header_data_without_pow_artefacts', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='validate_proof_of_work', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the Proof of Work constraints.\n\n In order to verify that a miner's proof-of-work is valid for a block, a\n ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``\n hash function. The mix digest is a hash of the header and the nonce that\n is passed through and it confirms whether or not proof-of-work was done\n on the correct block. The result is the actual hash value of the block.\n\n Parameters\n ----------\n header :\n Header of interest.\n ")), + Assign( + targets=[ + Name(id='header_hash', ctx=Store())], + value=Call( + func=Name(id='generate_header_hash_for_pow', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache', ctx=Store())], + value=Call( + func=Name(id='generate_cache', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='mix_digest', ctx=Store()), + Name(id='result', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='hashimoto_light', ctx=Load()), + args=[ + Name(id='header_hash', ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + Name(id='cache', ctx=Load()), + Call( + func=Name(id='dataset_size', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='mix_digest', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='mix_digest', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='limit', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='limit', ctx=Load()), + op=FloorDiv(), + right=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n gas_available :\n The gas remaining in the block.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + Return( + value=Name(id='sender_address', ctx=Load()))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='post_state', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n post_state :\n The state root immediately after this transaction.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='post_state', + value=Name(id='post_state', ctx=Load())), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + Return( + value=Name(id='receipt', ctx=Load()))], + decorator_list=[], + returns=Name(id='Receipt', ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='block_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n block_difficulty :\n Difficulty of the block.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='transactions', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='tx', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='gas_available', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='gas_price', + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='difficulty', + value=Name(id='block_difficulty', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[]), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='pay_rewards', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='block_number', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='ommers', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='validate_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='block_header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the ommers mentioned in the block.\n\n An ommer block is a block that wasn't canonically added to the\n blockchain because it wasn't validated as fast as the canonical block\n but was mined at the same time.\n\n To be considered valid, the ommers must adhere to the rules defined in\n the Ethereum protocol. The maximum amount of ommers is 2 per block and\n there cannot be duplicate ommers in a block. Many of the other ommer\n constraints are listed in the in-line comments of this function.\n\n Parameters\n ----------\n ommers :\n List of ommers mentioned in the current block.\n block_header:\n The header of current block.\n chain :\n History and current state.\n ")), + Assign( + targets=[ + Name(id='block_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='block_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='ommers_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return()], + orelse=[]), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + op=Sub(), + right=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Name(id='ommer', ctx=Load()), + Name(id='ommer_parent_header', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=2)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommers_hashes', ctx=Store())], + value=ListComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + ifs=[], + is_async=0)])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[])], + keywords=[])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_canonical_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=BinOp( + left=Name(id='MAX_OMMER_DEPTH', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + ctx=Load())), + Assign( + targets=[ + Name(id='recent_canonical_block_hashes', ctx=Store())], + value=SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='recent_ommers_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + simple=1), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='recent_ommers_hashes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='recent_ommers_hashes', ctx=Load()), + attr='union', + ctx=Load()), + args=[ + SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='ommer_index', ctx=Store()), + Name(id='ommer', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='ommer_hash', ctx=Store())], + value=Subscript( + value=Name(id='ommers_hashes', ctx=Load()), + slice=Name(id='ommer_index', ctx=Load()), + ctx=Load())), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='block_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_ommers_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='ommer_age', ctx=Load())]), + Compare( + left=Name(id='ommer_age', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_OMMER_DEPTH', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='parent_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pay_rewards', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pay rewards to the block miner as well as the ommers miners.\n\n The miner of the canonical block is rewarded with the predetermined\n block reward, ``BLOCK_REWARD``, plus a variable award based off of the\n number of ommer blocks that were mined around the same time, and included\n in the canonical block's header. An ommer block is a block that wasn't\n added to the canonical blockchain because it wasn't validated as fast as\n the accepted block but was mined at the same time. Although not all blocks\n that are mined are added to the canonical chain, miners are still paid a\n reward for their efforts. This reward is called an ommer reward and is\n calculated based on the number associated with the ommer block that they\n mined.\n\n Parameters\n ----------\n state :\n Current account state.\n block_number :\n Position of the block within the chain.\n coinbase :\n Address of account which receives block reward and transaction fees.\n ommers :\n List of ommers mentioned in the current block.\n ")), + Assign( + targets=[ + Name(id='ommer_count', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='miner_reward', ctx=Store())], + value=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='ommer_count', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='miner_reward', ctx=Load())], + keywords=[])), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_number', ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='ommer_miner_reward', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Sub(), + right=Name(id='ommer_age', ctx=Load())), + op=Mult(), + right=Name(id='BLOCK_REWARD', ctx=Load())), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='ommer_miner_reward', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[])), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Name(id='TX_CREATE_COST', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='v', ctx=Store()), + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=28)])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Compute the hash of a transaction used in the signature.\n\n The values that are used to compute the signing hash set the rules for a\n transaction. For example, signing over the gas sets a limit for the\n amount of money that is allowed to be pulled out of the sender's account.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_difficulty', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes difficulty of a block using its header and parent header.\n\n The difficulty is determined by the time the block was created after its\n parent. The ``offset`` is calculated using the parent block's difficulty,\n ``parent_difficulty``, and the timestamp between blocks. This offset is\n then added to the parent difficulty and is stored as the ``difficulty``\n variable. If the time between the block and its parent is too short, the\n offset will result in a positive number thus making the sum of\n ``parent_difficulty`` and ``offset`` to be a greater value in order to\n avoid mass forking. But, if the time is long enough, then the offset\n results in a negative value making the block less difficult than\n its parent.\n\n The base standard for a block's difficulty is the predefined value\n set for the genesis block since it has no parent. So, a block\n can't be less difficult than the genesis block, therefore each block's\n difficulty is set to the maximum value between the calculated\n difficulty and the ``GENESIS_DIFFICULTY``.\n\n Parameters\n ----------\n block_number :\n Block number of the block.\n block_timestamp :\n Timestamp of the block.\n parent_timestamp :\n Timestamp of the parent block.\n parent_difficulty :\n difficulty of the parent block.\n\n Returns\n -------\n difficulty : `ethereum.base_types.Uint`\n Computed difficulty for a block.\n ")), + Assign( + targets=[ + Name(id='offset', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=2048)), + op=Mult(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=Constant(value=1), + op=Sub(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_timestamp', ctx=Load()), + op=Sub(), + right=Name(id='parent_timestamp', ctx=Load()))], + keywords=[]), + op=FloorDiv(), + right=Constant(value=10))), + UnaryOp( + op=USub(), + operand=Constant(value=99))], + keywords=[]))), + Assign( + targets=[ + Name(id='difficulty', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='offset', ctx=Load()))), + Assign( + targets=[ + Name(id='num_bomb_periods', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=100000)), + op=Sub(), + right=Constant(value=2))), + If( + test=Compare( + left=Name(id='num_bomb_periods', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='difficulty', ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Name(id='num_bomb_periods', ctx=Load())))], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='difficulty', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/fork.v b/coq/ethereum/dao_fork/fork.v new file mode 100644 index 0000000000..fe9204c2b4 --- /dev/null +++ b/coq/ethereum/dao_fork/fork.v @@ -0,0 +1,845 @@ +(* Generated *) +(* +.. _dao-fork: + +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.ethash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.dao_fork.__init__. +Require ethereum.dao_fork.blocks. +Require ethereum.dao_fork.bloom. +Require ethereum.dao_fork.dao. +Require ethereum.dao_fork.fork_types. +Require ethereum.dao_fork.state. +Require ethereum.dao_fork.transactions. +Require ethereum.dao_fork.trie. +Require ethereum.dao_fork.utils.message. +Require ethereum.dao_fork.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 + `_ 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. + *) + do* [[ dao.apply_dao ~(| + M.get_field ~(| old, "state" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + do* [[ M.get_local ~(| "validate_ommers" |) ~(| + M.get_field ~(| block, "ommers" |), + M.get_field ~(| block, "header" |), + chain + |) ]] in + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "difficulty" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| block, "ommers" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_difficulty" [[ + M.get_local ~(| "calculate_block_difficulty" |) ~(| + M.get_field ~(| header, "number" |), + M.get_field ~(| header, "timestamp" |), + M.get_field ~(| parent_header, "timestamp" |), + M.get_field ~(| parent_header, "difficulty" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| + header + |) ]] in + M.pure tt. + +Definition generate_header_hash_for_pow (header : Header) : M Hash32 := + (* + 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. + *) + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_proof_of_work (header : Header) : M unit := + (* + 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. + *) + do* M.assign "header_hash" [[ + M.get_local ~(| "generate_header_hash_for_pow" |) ~(| + header + |) in + ]] in + do* M.assign "cache" [[ + ethereum.ethash.generate_cache ~(| + M.get_field ~(| header, "number" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (gas_available : Uint) : M 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. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + tx + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (post_state : Bytes32) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (block_gas_limit : Uint) (block_time : U256) (block_difficulty : Uint) (transactions : (* TODO type *)) (ommers : (* TODO type *)) : M ApplyBodyOutput := + (* + 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 + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "pay_rewards" |) ~(| + state, + block_number, + coinbase, + ommers + |) ]] in + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_ommers (ommers : (* TODO type *)) (block_header : Header) (chain : BlockChain) : M unit := + (* + 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. + *) + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_canonical_blocks" [[ + (* TODO expression *) in + ]] in + do* M.assign "recent_canonical_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition pay_rewards (state : State) (block_number : Uint) (coinbase : Address) (ommers : (* TODO type *)) : M unit := + (* + 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. + *) + do* M.assign "ommer_count" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + ommers + |) + |) in + ]] in + do* M.assign "miner_reward" [[ + (* TODO expression *) in + ]] in + do* [[ state.create_ether ~(| + state, + coinbase, + M.get_local ~(| "miner_reward" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + do* M.assign "gas_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| env, "coinbase" |), + M.get_local ~(| "coinbase_balance_after_mining_fee" |) + |) ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "public_key" [[ + ethereum.crypto.elliptic_curve.secp256k1_recover ~(| + M.get_local ~(| "r" |), + M.get_local ~(| "s" |), + (* TODO expression *), + M.get_local ~(| "signing_hash" |) ~(| + tx + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition signing_hash (tx : Transaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_block_difficulty (block_number : Uint) (block_timestamp : U256) (parent_timestamp : U256) (parent_difficulty : Uint) : M Uint := + (* + 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. + *) + do* M.assign "offset" [[ + (* TODO expression *) in + ]] in + do* M.assign "difficulty" [[ + (* TODO expression *) in + ]] in + do* M.assign "num_bomb_periods" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/fork_types.ast b/coq/ethereum/dao_fork/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/dao_fork/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/fork_types.v b/coq/ethereum/dao_fork/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/dao_fork/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/state.ast b/coq/ethereum/dao_fork/state.ast new file mode 100644 index 0000000000..dce2e294a9 --- /dev/null +++ b/coq/ethereum/dao_fork/state.ast @@ -0,0 +1,1292 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add newly created ether to an account.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to which ether is added.\n amount:\n The amount of ether to be added to the account of interest.\n ')), + FunctionDef( + name='increase_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/state.v b/coq/ethereum/dao_fork/state.v new file mode 100644 index 0000000000..917493dc44 --- /dev/null +++ b/coq/ethereum/dao_fork/state.v @@ -0,0 +1,484 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.dao_fork.fork_types. +Require ethereum.dao_fork.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := + (* + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/transactions.ast b/coq/ethereum/dao_fork/transactions.ast new file mode 100644 index 0000000000..19d5c9707f --- /dev/null +++ b/coq/ethereum/dao_fork/transactions.ast @@ -0,0 +1,106 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + ClassDef( + name='Transaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/transactions.v b/coq/ethereum/dao_fork/transactions.v new file mode 100644 index 0000000000..d113f3f58f --- /dev/null +++ b/coq/ethereum/dao_fork/transactions.v @@ -0,0 +1,13 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.dao_fork.fork_types. diff --git a/coq/ethereum/dao_fork/trie.ast b/coq/ethereum/dao_fork/trie.ast new file mode 100644 index 0000000000..ee3fa15e2a --- /dev/null +++ b/coq/ethereum/dao_fork/trie.ast @@ -0,0 +1,1618 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.homestead', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.RLP`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/trie.v b/coq/ethereum/dao_fork/trie.v new file mode 100644 index 0000000000..6b8953f256 --- /dev/null +++ b/coq/ethereum/dao_fork/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/utils/__init__.ast b/coq/ethereum/dao_fork/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/dao_fork/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/utils/__init__.v b/coq/ethereum/dao_fork/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/dao_fork/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/dao_fork/utils/address.ast b/coq/ethereum/dao_fork/utils/address.ast new file mode 100644 index 0000000000..57ffba1535 --- /dev/null +++ b/coq/ethereum/dao_fork/utils/address.ast @@ -0,0 +1,139 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this Dao Fork version of specification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `ethereum.dao_fork.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/utils/address.v b/coq/ethereum/dao_fork/utils/address.v new file mode 100644 index 0000000000..ae6dafeeff --- /dev/null +++ b/coq/ethereum/dao_fork/utils/address.v @@ -0,0 +1,74 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this Dao Fork version of specification. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.dao_fork.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.dao_fork.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/utils/hexadecimal.ast b/coq/ethereum/dao_fork/utils/hexadecimal.ast new file mode 100644 index 0000000000..4d8f93a273 --- /dev/null +++ b/coq/ethereum/dao_fork/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to Dao Fork\ntypes.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/utils/hexadecimal.v b/coq/ethereum/dao_fork/utils/hexadecimal.v new file mode 100644 index 0000000000..e4b373176a --- /dev/null +++ b/coq/ethereum/dao_fork/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to Dao Fork +types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.dao_fork.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/utils/message.ast b/coq/ethereum/dao_fork/utils/message.ast new file mode 100644 index 0000000000..66582b55b2 --- /dev/null +++ b/coq/ethereum/dao_fork/utils/message.ast @@ -0,0 +1,234 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this Dao Fork version of specification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True)]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n\n Returns\n -------\n message: `ethereum.dao_fork.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/utils/message.v b/coq/ethereum/dao_fork/utils/message.v new file mode 100644 index 0000000000..1cc3cf4313 --- /dev/null +++ b/coq/ethereum/dao_fork/utils/message.v @@ -0,0 +1,56 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this Dao Fork version of specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.dao_fork.fork_types. +Require ethereum.dao_fork.state. +Require ethereum.dao_fork.vm. +Require ethereum.dao_fork.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + + Returns + ------- + message: `ethereum.dao_fork.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/__init__.ast b/coq/ethereum/dao_fork/vm/__init__.ast new file mode 100644 index 0000000000..b679ec6d01 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/__init__.ast @@ -0,0 +1,362 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State')], + level=2), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/__init__.v b/coq/ethereum/dao_fork/vm/__init__.v new file mode 100644 index 0000000000..97024ca4f8 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/__init__.v @@ -0,0 +1,65 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.dao_fork.blocks. +Require ethereum.dao_fork.fork_types. +Require ethereum.dao_fork.state. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/exceptions.ast b/coq/ethereum/dao_fork/vm/exceptions.ast new file mode 100644 index 0000000000..3194c3c232 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/exceptions.ast @@ -0,0 +1,125 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/exceptions.v b/coq/ethereum/dao_fork/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/dao_fork/vm/gas.ast b/coq/ethereum/dao_fork/vm/gas.ast new file mode 100644 index 0000000000..675fef92a5 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/gas.ast @@ -0,0 +1,759 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists')], + level=2), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXTERNAL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BALANCE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=40)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='REFUND_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=24000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount for executing Opcodes `CALL` and `CALLCODE`.\n\n Parameters\n ----------\n state :\n The current state.\n gas :\n The amount of gas provided to the message-call.\n to:\n The address of the recipient account.\n value:\n The amount of `ETH` that needs to be transferred.\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='gas', ctx=Load())), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))), + Assign( + targets=[ + Name(id='stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Name(id='gas', ctx=Load()), + orelse=BinOp( + left=Name(id='GAS_CALL_STIPEND', ctx=Load()), + op=Add(), + right=Name(id='gas', ctx=Load())))), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + Name(id='cost', ctx=Load()), + Name(id='stipend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/gas.v b/coq/ethereum/dao_fork/vm/gas.v new file mode 100644 index 0000000000..d5b4511bf7 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/gas.v @@ -0,0 +1,149 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.dao_fork.fork_types. +Require ethereum.dao_fork.state. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (state : State) (gas : Uint) (to : Address) (value : U256) : M MessageCallGas := + (* + Calculates the gas amount for executing Opcodes `CALL` and `CALLCODE`. + + Parameters + ---------- + state : + The current state. + gas : + The amount of gas provided to the message-call. + to: + The address of the recipient account. + value: + The amount of `ETH` that needs to be transferred. + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/instructions/__init__.ast b/coq/ethereum/dao_fork/vm/instructions/__init__.ast new file mode 100644 index 0000000000..0931c390c8 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/__init__.ast @@ -0,0 +1,1648 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='DIFFICULTY', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIFFICULTY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/instructions/__init__.v b/coq/ethereum/dao_fork/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/dao_fork/vm/instructions/arithmetic.ast b/coq/ethereum/dao_fork/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/instructions/arithmetic.v b/coq/ethereum/dao_fork/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..d825516ace --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/instructions/bitwise.ast b/coq/ethereum/dao_fork/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..73dc9f4a45 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/bitwise.ast @@ -0,0 +1,418 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/instructions/bitwise.v b/coq/ethereum/dao_fork/vm/instructions/bitwise.v new file mode 100644 index 0000000000..0397f10c19 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/bitwise.v @@ -0,0 +1,196 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/instructions/block.ast b/coq/ethereum/dao_fork/vm/instructions/block.ast new file mode 100644 index 0000000000..cc66857e82 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/block.ast @@ -0,0 +1,437 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's difficulty onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/instructions/block.v b/coq/ethereum/dao_fork/vm/instructions/block.v new file mode 100644 index 0000000000..a3799da32a --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/block.v @@ -0,0 +1,213 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition difficulty (evm : Evm) : M unit := + (* + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/instructions/comparison.ast b/coq/ethereum/dao_fork/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/instructions/comparison.v b/coq/ethereum/dao_fork/vm/instructions/comparison.v new file mode 100644 index 0000000000..87b493c750 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/instructions/control_flow.ast b/coq/ethereum/dao_fork/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/instructions/control_flow.v b/coq/ethereum/dao_fork/vm/instructions/control_flow.v new file mode 100644 index 0000000000..e71d79a9db --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.exceptions. +Require ethereum.dao_fork.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/instructions/environment.ast b/coq/ethereum/dao_fork/vm/instructions/environment.ast new file mode 100644 index 0000000000..15f88ad9cc --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/environment.ast @@ -0,0 +1,1199 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BALANCE'), + alias(name='GAS_BASE'), + alias(name='GAS_COPY'), + alias(name='GAS_EXTERNAL'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BALANCE', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_EXTERNAL', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_EXTERNAL', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/instructions/environment.v b/coq/ethereum/dao_fork/vm/instructions/environment.v new file mode 100644 index 0000000000..16113bad15 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/environment.v @@ -0,0 +1,552 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.dao_fork.state. +Require ethereum.dao_fork.utils.address. +Require ethereum.dao_fork.vm.memory. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BALANCE + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_EXTERNAL + |) ]] in + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/instructions/keccak.ast b/coq/ethereum/dao_fork/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/instructions/keccak.v b/coq/ethereum/dao_fork/vm/instructions/keccak.v new file mode 100644 index 0000000000..c8d1583221 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.memory. +Require ethereum.dao_fork.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/instructions/log.ast b/coq/ethereum/dao_fork/vm/instructions/log.ast new file mode 100644 index 0000000000..d3bf292c44 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/log.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/instructions/log.v b/coq/ethereum/dao_fork/vm/instructions/log.v new file mode 100644 index 0000000000..916178e9a1 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/log.v @@ -0,0 +1,77 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.dao_fork.blocks. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.memory. +Require ethereum.dao_fork.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/instructions/memory.ast b/coq/ethereum/dao_fork/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/instructions/memory.v b/coq/ethereum/dao_fork/vm/instructions/memory.v new file mode 100644 index 0000000000..16d2dcf365 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.memory. +Require ethereum.dao_fork.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/instructions/stack.ast b/coq/ethereum/dao_fork/vm/instructions/stack.ast new file mode 100644 index 0000000000..95cfc0b6cf --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/stack.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/instructions/stack.v b/coq/ethereum/dao_fork/vm/instructions/stack.v new file mode 100644 index 0000000000..aa06094c40 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/stack.v @@ -0,0 +1,153 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.exceptions. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/instructions/storage.ast b/coq/ethereum/dao_fork/vm/instructions/storage.ast new file mode 100644 index 0000000000..7ce9b2f17f --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/storage.ast @@ -0,0 +1,278 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_SLOAD', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_UPDATE', ctx=Load()))]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/instructions/storage.v b/coq/ethereum/dao_fork/vm/instructions/storage.v new file mode 100644 index 0000000000..9abde01736 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/storage.v @@ -0,0 +1,108 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.dao_fork.state. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_SLOAD + |) ]] in + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/instructions/system.ast b/coq/ethereum/dao_fork/vm/instructions/system.ast new file mode 100644 index 0000000000..91e4fc3a4a --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/system.ast @@ -0,0 +1,1863 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL'), + alias(name='GAS_CREATE'), + alias(name='GAS_ZERO'), + alias(name='REFUND_SELF_DESTRUCT'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])])]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_ZERO', ctx=Load())), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='refunded_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load())), + While( + test=Compare( + left=Name(id='parent_evm', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='refunded_accounts', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='originator', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='refunded_accounts', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='REFUND_SELF_DESTRUCT', ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='gas', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/instructions/system.v b/coq/ethereum/dao_fork/vm/instructions/system.v new file mode 100644 index 0000000000..d62c357948 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/instructions/system.v @@ -0,0 +1,487 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.dao_fork.fork_types. +Require ethereum.dao_fork.state. +Require ethereum.dao_fork.utils.address. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.memory. +Require ethereum.dao_fork.vm.stack. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "create_message_gas" [[ + M.get_field ~(| evm, "gas_left" |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "gas" |), + M.get_local ~(| "to" |), + M.get_local ~(| "value" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "gas" |), + M.get_local ~(| "to" |), + M.get_local ~(| "value" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_ZERO in + ]] in + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "refunded_accounts" [[ + M.get_field ~(| evm, "accounts_to_delete" |) in + ]] in + do* M.assign "parent_evm" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "parent_evm" |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_local ~(| "gas" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/interpreter.ast b/coq/ethereum/dao_fork/vm/interpreter.ast new file mode 100644 index 0000000000..074b265594 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/interpreter.ast @@ -0,0 +1,975 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidOpcode'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.dao_fork.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.dao_fork.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='error', + value=Constant(value=None))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/interpreter.v b/coq/ethereum/dao_fork/vm/interpreter.v new file mode 100644 index 0000000000..4c01fccc89 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/interpreter.v @@ -0,0 +1,165 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.dao_fork.blocks. +Require ethereum.dao_fork.fork_types. +Require ethereum.dao_fork.state. +Require ethereum.dao_fork.vm. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.precompiled_contracts.mapping. +Require ethereum.dao_fork.vm.__init__. +Require ethereum.dao_fork.vm.exceptions. +Require ethereum.dao_fork.vm.instructions. +Require ethereum.dao_fork.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.dao_fork.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.dao_fork.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/memory.ast b/coq/ethereum/dao_fork/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/memory.v b/coq/ethereum/dao_fork/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/dao_fork/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/__init__.ast b/coq/ethereum/dao_fork/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..2ac4916772 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,52 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/__init__.v b/coq/ethereum/dao_fork/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..1b2d6cca57 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.dao_fork.utils.hexadecimal. diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..b3b37058be --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.dao_fork.vm. +Require ethereum.dao_fork.vm.gas. +Require ethereum.dao_fork.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/identity.ast b/coq/ethereum/dao_fork/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/identity.v b/coq/ethereum/dao_fork/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..d65c4f900a --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.dao_fork.vm. +Require ethereum.dao_fork.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/mapping.ast b/coq/ethereum/dao_fork/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..de162645ff --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,65 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/mapping.v b/coq/ethereum/dao_fork/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..f3b02e3260 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/mapping.v @@ -0,0 +1,22 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.dao_fork.fork_types. +Require ethereum.dao_fork.vm.precompiled_contracts.__init__. +Require ethereum.dao_fork.vm.precompiled_contracts.ecrecover. +Require ethereum.dao_fork.vm.precompiled_contracts.identity. +Require ethereum.dao_fork.vm.precompiled_contracts.ripemd160. +Require ethereum.dao_fork.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/sha256.ast b/coq/ethereum/dao_fork/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/precompiled_contracts/sha256.v b/coq/ethereum/dao_fork/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/dao_fork/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/runtime.ast b/coq/ethereum/dao_fork/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/runtime.v b/coq/ethereum/dao_fork/vm/runtime.v new file mode 100644 index 0000000000..308e435285 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.dao_fork.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/dao_fork/vm/stack.ast b/coq/ethereum/dao_fork/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/dao_fork/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/dao_fork/vm/stack.v b/coq/ethereum/dao_fork/vm/stack.v new file mode 100644 index 0000000000..77380a95d6 --- /dev/null +++ b/coq/ethereum/dao_fork/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.dao_fork.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/ethash.ast b/coq/ethereum/ethash.ast new file mode 100644 index 0000000000..a62f5f32af --- /dev/null +++ b/coq/ethereum/ethash.ast @@ -0,0 +1,1355 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthash is a proof-of-work algorithm designed to be [ASIC] resistant through\n[memory hardness][mem-hard].\n\nTo achieve memory hardness, computing Ethash requires access to subsets of a\nlarge structure. The particular subsets chosen are based on the nonce and block\nheader, while the set itself is changed every [`epoch`].\n\nAt a high level, the Ethash algorithm is as follows:\n\n1. Create a **seed** value, generated with [`generate_seed`] and based on the\n preceding block numbers.\n1. From the seed, compute a pseudorandom **cache** with [`generate_cache`].\n1. From the cache, generate a **dataset** with [`generate_dataset`]. The\n dataset grows over time based on [`DATASET_EPOCH_GROWTH_SIZE`].\n1. Miners hash slices of the dataset together, which is where the memory\n hardness is introduced. Verification of the proof-of-work only requires the\n cache to be able to recompute a much smaller subset of the full dataset.\n\n[`DATASET_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.DATASET_EPOCH_GROWTH_SIZE\n[`generate_dataset`]: ref:ethereum.ethash.generate_dataset\n[`generate_cache`]: ref:ethereum.ethash.generate_cache\n[`generate_seed`]: ref:ethereum.ethash.generate_seed\n[`epoch`]: ref:ethereum.ethash.epoch\n[ASIC]: https://en.wikipedia.org/wiki/Application-specific_integrated_circuit\n[mem-hard]: https://en.wikipedia.org/wiki/Memory-hard_function\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes8')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U32'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='Hash64'), + alias(name='keccak256'), + alias(name='keccak512')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='is_prime'), + alias(name='le_bytes_to_uint32_sequence'), + alias(name='le_uint32_sequence_to_bytes'), + alias(name='le_uint32_sequence_to_uint')], + level=0), + Assign( + targets=[ + Name(id='EPOCH_SIZE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30000)], + keywords=[])), + Expr( + value=Constant(value='\nNumber of blocks before a dataset needs to be regenerated (known as an\n"epoch".) See [`epoch`].\n\n[`epoch`]: ref:ethereum.ethash.epoch\n')), + Assign( + targets=[ + Name(id='INITIAL_CACHE_SIZE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=24))], + keywords=[])), + Expr( + value=Constant(value="\nSize of the cache (in bytes) during the first epoch. Each subsequent epoch's\ncache roughly grows by [`CACHE_EPOCH_GROWTH_SIZE`] bytes. See [`cache_size`].\n\n[`CACHE_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.CACHE_EPOCH_GROWTH_SIZE\n[`cache_size`]: ref:ethereum.ethash.cache_size\n")), + Assign( + targets=[ + Name(id='CACHE_EPOCH_GROWTH_SIZE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=17))], + keywords=[])), + Expr( + value=Constant(value='\nAfter the first epoch, the cache size grows by roughly this amount. See\n[`cache_size`].\n\n[`cache_size`]: ref:ethereum.ethash.cache_size\n')), + Assign( + targets=[ + Name(id='INITIAL_DATASET_SIZE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=30))], + keywords=[])), + Expr( + value=Constant(value="\nSize of the dataset (in bytes) during the first epoch. Each subsequent epoch's\ndataset roughly grows by [`DATASET_EPOCH_GROWTH_SIZE`] bytes. See\n[`dataset_size`].\n\n[`DATASET_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.DATASET_EPOCH_GROWTH_SIZE\n[`dataset_size`]: ref:ethereum.ethash.dataset_size\n")), + Assign( + targets=[ + Name(id='DATASET_EPOCH_GROWTH_SIZE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=23))], + keywords=[])), + Expr( + value=Constant(value='\nAfter the first epoch, the dataset size grows by roughly this amount. See\n[`dataset_size`].\n\n[`dataset_size`]: ref:ethereum.ethash.dataset_size\n')), + Assign( + targets=[ + Name(id='HASH_BYTES', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[])), + Expr( + value=Constant(value='\nLength of a hash, in bytes.\n')), + Assign( + targets=[ + Name(id='MIX_BYTES', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=128)], + keywords=[])), + Expr( + value=Constant(value='\nWidth of mix, in bytes. See [`generate_dataset_item`].\n\n[`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item\n')), + Assign( + targets=[ + Name(id='CACHE_ROUNDS', ctx=Store())], + value=Constant(value=3)), + Expr( + value=Constant(value='\nNumber of times to repeat the [`keccak512`] step while generating the hash. See\n[`generate_cache`].\n\n[`keccak512`]: ref:ethereum.crypto.hash.keccak512\n[`generate_cache`]: ref:ethereum.ethash.generate_cache\n')), + Assign( + targets=[ + Name(id='DATASET_PARENTS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])), + Expr( + value=Constant(value='\nNumber of parents of each dataset element. See [`generate_dataset_item`].\n\n[`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item\n')), + Assign( + targets=[ + Name(id='HASHIMOTO_ACCESSES', ctx=Store())], + value=Constant(value=64)), + Expr( + value=Constant(value='\nNumber of accesses in the [`hashimoto`] loop.\n\n[`hashimoto`]: ref:ethereum.ethash.hashimoto\n')), + FunctionDef( + name='epoch', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the epoch number to which the block identified by `block_number`\n belongs. The first epoch is numbered zero.\n\n An Ethash epoch is a fixed number of blocks ([`EPOCH_SIZE`]) long, during\n which the dataset remains constant. At the end of each epoch, the dataset\n is generated anew. See [`generate_dataset`].\n\n [`EPOCH_SIZE`]: ref:ethereum.ethash.EPOCH_SIZE\n [`generate_dataset`]: ref:ethereum.ethash.generate_dataset\n ')), + Return( + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=FloorDiv(), + right=Name(id='EPOCH_SIZE', ctx=Load())))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='cache_size', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the cache size (in bytes) of the epoch to which `block_number`\n belongs.\n\n See [`INITIAL_CACHE_SIZE`] and [`CACHE_EPOCH_GROWTH_SIZE`] for the initial\n size and linear growth rate, respectively. The cache is generated in\n [`generate_cache`].\n\n The actual cache size is smaller than simply multiplying\n `CACHE_EPOCH_GROWTH_SIZE` by the epoch number to minimize the risk of\n unintended cyclic behavior. It is defined as the highest prime number below\n what linear growth would calculate.\n\n [`INITIAL_CACHE_SIZE`]: ref:ethereum.ethash.INITIAL_CACHE_SIZE\n [`CACHE_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.CACHE_EPOCH_GROWTH_SIZE\n [`generate_cache`]: ref:ethereum.ethash.generate_cache\n ')), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=BinOp( + left=Name(id='INITIAL_CACHE_SIZE', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='CACHE_EPOCH_GROWTH_SIZE', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='epoch', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[])))), + AugAssign( + target=Name(id='size', ctx=Store()), + op=Sub(), + value=Name(id='HASH_BYTES', ctx=Load())), + While( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_prime', ctx=Load()), + args=[ + BinOp( + left=Name(id='size', ctx=Load()), + op=FloorDiv(), + right=Name(id='HASH_BYTES', ctx=Load()))], + keywords=[])), + body=[ + AugAssign( + target=Name(id='size', ctx=Store()), + op=Sub(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]), + op=Mult(), + right=Name(id='HASH_BYTES', ctx=Load())))], + orelse=[]), + Return( + value=Name(id='size', ctx=Load()))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='dataset_size', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the dataset size (in bytes) of the epoch to which `block_number`\n belongs.\n\n See [`INITIAL_DATASET_SIZE`] and [`DATASET_EPOCH_GROWTH_SIZE`][ds] for the\n initial size and linear growth rate, respectively. The complete dataset is\n generated in [`generate_dataset`], while the slices used in verification\n are generated in [`generate_dataset_item`].\n\n The actual dataset size is smaller than simply multiplying\n `DATASET_EPOCH_GROWTH_SIZE` by the epoch number to minimize the risk of\n unintended cyclic behavior. It is defined as the highest prime number below\n what linear growth would calculate.\n\n [`INITIAL_DATASET_SIZE`]: ref:ethereum.ethash.INITIAL_DATASET_SIZE\n [ds]: ref:ethereum.ethash.DATASET_EPOCH_GROWTH_SIZE\n [`generate_dataset`]: ref:ethereum.ethash.generate_dataset\n [`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item\n ')), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=BinOp( + left=Name(id='INITIAL_DATASET_SIZE', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='DATASET_EPOCH_GROWTH_SIZE', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='epoch', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[])))), + AugAssign( + target=Name(id='size', ctx=Store()), + op=Sub(), + value=Name(id='MIX_BYTES', ctx=Load())), + While( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_prime', ctx=Load()), + args=[ + BinOp( + left=Name(id='size', ctx=Load()), + op=FloorDiv(), + right=Name(id='MIX_BYTES', ctx=Load()))], + keywords=[])), + body=[ + AugAssign( + target=Name(id='size', ctx=Store()), + op=Sub(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]), + op=Mult(), + right=Name(id='MIX_BYTES', ctx=Load())))], + orelse=[]), + Return( + value=Name(id='size', ctx=Load()))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='generate_seed', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the cache generation seed for the block identified by\n `block_number`. See [`generate_cache`].\n\n [`generate_cache`]: ref:ethereum.ethash.generate_cache\n ')), + Assign( + targets=[ + Name(id='epoch_number', ctx=Store())], + value=Call( + func=Name(id='epoch', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='seed', ctx=Store())], + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=32))), + While( + test=Compare( + left=Name(id='epoch_number', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='seed', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='seed', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='epoch_number', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='seed', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='generate_cache', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Generate the cache for the block identified by `block_number`. See\n [`generate_dataset`] for how the cache is used.\n\n The cache is generated in two steps: filling the array with a chain of\n [`keccak512`] hashes, then running two rounds of Sergio Demian Lerner's\n [RandMemoHash] on those bytes.\n\n [`keccak512`]: ref:ethereum.crypto.hash.keccak512\n [`generate_dataset`]: ref:ethereum.ethash.generate_dataset\n [RandMemoHash]: http://www.hashcash.org/papers/memohash.pdf\n ")), + Assign( + targets=[ + Name(id='seed', ctx=Store())], + value=Call( + func=Name(id='generate_seed', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache_size_bytes', ctx=Store())], + value=Call( + func=Name(id='cache_size', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache_size_words', ctx=Store())], + value=BinOp( + left=Name(id='cache_size_bytes', ctx=Load()), + op=FloorDiv(), + right=Name(id='HASH_BYTES', ctx=Load()))), + Assign( + targets=[ + Name(id='cache', ctx=Store())], + value=List( + elts=[ + Call( + func=Name(id='keccak512', ctx=Load()), + args=[ + Name(id='seed', ctx=Load())], + keywords=[])], + ctx=Load())), + For( + target=Name(id='index', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Name(id='cache_size_words', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='cache_item', ctx=Store())], + value=Call( + func=Name(id='keccak512', ctx=Load()), + args=[ + Subscript( + value=Name(id='cache', ctx=Load()), + slice=BinOp( + left=Name(id='index', ctx=Load()), + op=Sub(), + right=Constant(value=1)), + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='cache', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='cache_item', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='CACHE_ROUNDS', ctx=Load())], + keywords=[]), + body=[ + For( + target=Name(id='index', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='cache_size_words', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='first_cache_item', ctx=Store())], + value=Subscript( + value=Name(id='cache', ctx=Load()), + slice=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='index', ctx=Load()), + op=Sub(), + right=Constant(value=1)), + op=Add(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='cache_size_words', ctx=Load())], + keywords=[])), + op=Mod(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='cache_size_words', ctx=Load())], + keywords=[])), + ctx=Load())), + Assign( + targets=[ + Name(id='second_cache_item', ctx=Store())], + value=Subscript( + value=Name(id='cache', ctx=Load()), + slice=BinOp( + left=Call( + func=Attribute( + value=Name(id='U32', ctx=Load()), + attr='from_le_bytes', + ctx=Load()), + args=[ + Subscript( + value=Subscript( + value=Name(id='cache', ctx=Load()), + slice=Name(id='index', ctx=Load()), + ctx=Load()), + slice=Slice( + lower=Constant(value=0), + upper=Constant(value=4)), + ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='U32', ctx=Load()), + args=[ + Name(id='cache_size_words', ctx=Load())], + keywords=[])), + ctx=Load())), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + ListComp( + elt=BinOp( + left=Name(id='a', ctx=Load()), + op=BitXor(), + right=Name(id='b', ctx=Load())), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='a', ctx=Store()), + Name(id='b', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='zip', ctx=Load()), + args=[ + Name(id='first_cache_item', ctx=Load()), + Name(id='second_cache_item', ctx=Load())], + keywords=[]), + ifs=[], + is_async=0)])], + keywords=[])), + Assign( + targets=[ + Subscript( + value=Name(id='cache', ctx=Load()), + slice=Name(id='index', ctx=Load()), + ctx=Store())], + value=Call( + func=Name(id='keccak512', ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + GeneratorExp( + elt=Call( + func=Name(id='le_bytes_to_uint32_sequence', ctx=Load()), + args=[ + Name(id='cache_item', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='cache_item', ctx=Store()), + iter=Name(id='cache', ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='fnv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U32', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='b', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U32', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n A non-associative substitute for XOR, inspired by the [FNV] hash by Fowler,\n Noll, and Vo. See [`fnv_hash`], [`generate_dataset_item`], and\n [`hashimoto`].\n\n Note that here we multiply the prime with the full 32-bit input, in\n contrast with the [FNV-1] spec which multiplies the prime with one byte\n (octet) in turn.\n\n [`hashimoto`]: ref:ethereum.ethash.hashimoto\n [`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item\n [`fnv_hash`]: ref:ethereum.ethash.fnv_hash\n [FNV]: https://w.wiki/XKZ\n [FNV-1]: http://www.isthe.com/chongo/tech/comp/fnv/#FNV-1\n ')), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=16777619)], + keywords=[])), + op=BitXor(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U32', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]))), + Return( + value=Call( + func=Name(id='U32', ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='U32', ctx=Load())), + FunctionDef( + name='fnv_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='mix_integers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='data', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Combines `data` into `mix_integers` using [`fnv`]. See [`hashimoto`] and\n [`generate_dataset_item`].\n\n [`hashimoto`]: ref:ethereum.ethash.hashimoto\n [`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item\n [`fnv`]: ref:ethereum.ethash.fnv\n ')), + Return( + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + GeneratorExp( + elt=Call( + func=Name(id='fnv', ctx=Load()), + args=[ + Subscript( + value=Name(id='mix_integers', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='data', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='mix_integers', ctx=Load())], + keywords=[])], + keywords=[]), + ifs=[], + is_async=0)])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='generate_dataset_item', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cache', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='index', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate a particular dataset item 0-indexed by `index` by hashing\n pseudorandomly-selected entries from `cache` together. See [`fnv`] and\n [`fnv_hash`] for the digest function, [`generate_cache`] for generating\n `cache`, and [`generate_dataset`] for the full dataset generation\n algorithm.\n\n [`fnv`]: ref:ethereum.ethash.fnv\n [`fnv_hash`]: ref:ethereum.ethash.fnv_hash\n [`generate_dataset`]: ref:ethereum.ethash.generate_dataset\n [`generate_cache`]: ref:ethereum.ethash.generate_cache\n ')), + Assign( + targets=[ + Name(id='mix', ctx=Store())], + value=Call( + func=Name(id='keccak512', ctx=Load()), + args=[ + Call( + func=Attribute( + value=BinOp( + left=Call( + func=Name(id='le_uint32_sequence_to_uint', ctx=Load()), + args=[ + Subscript( + value=Name(id='cache', ctx=Load()), + slice=BinOp( + left=Name(id='index', ctx=Load()), + op=Mod(), + right=Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='cache', ctx=Load())], + keywords=[])), + ctx=Load())], + keywords=[]), + op=BitXor(), + right=Name(id='index', ctx=Load())), + attr='to_le_bytes64', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='mix_integers', ctx=Store())], + value=Call( + func=Name(id='le_bytes_to_uint32_sequence', ctx=Load()), + args=[ + Name(id='mix', ctx=Load())], + keywords=[])), + For( + target=Name(id='j', ctx=Store()), + iter=GeneratorExp( + elt=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='k', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='DATASET_PARENTS', ctx=Load())], + keywords=[]), + ifs=[], + is_async=0)]), + body=[ + AnnAssign( + target=Name(id='mix_word', ctx=Store()), + annotation=Name(id='U32', ctx=Load()), + value=Subscript( + value=Name(id='mix_integers', ctx=Load()), + slice=BinOp( + left=Name(id='j', ctx=Load()), + op=Mod(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[])), + ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='cache_index', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='fnv', ctx=Load()), + args=[ + BinOp( + left=Name(id='index', ctx=Load()), + op=BitXor(), + right=Name(id='j', ctx=Load())), + Name(id='mix_word', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='U32', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='cache', ctx=Load())], + keywords=[])], + keywords=[]))), + Assign( + targets=[ + Name(id='parent', ctx=Store())], + value=Subscript( + value=Name(id='cache', ctx=Load()), + slice=Name(id='cache_index', ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='mix_integers', ctx=Store())], + value=Call( + func=Name(id='fnv_hash', ctx=Load()), + args=[ + Name(id='mix_integers', ctx=Load()), + Name(id='parent', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='mix', ctx=Store())], + value=Call( + func=Name(id='Hash64', ctx=Load()), + args=[ + Call( + func=Name(id='le_uint32_sequence_to_bytes', ctx=Load()), + args=[ + Name(id='mix_integers', ctx=Load())], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='keccak512', ctx=Load()), + args=[ + Name(id='mix', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash64', ctx=Load())), + FunctionDef( + name='generate_dataset', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate the full dataset for the block identified by `block_number`.\n\n This function is present only for demonstration purposes. It is not used\n while validating blocks.\n ')), + AnnAssign( + target=Name(id='dataset_size_bytes', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + value=Call( + func=Name(id='dataset_size', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + simple=1), + AnnAssign( + target=Name(id='cache', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='generate_cache', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + simple=1), + Return( + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + GeneratorExp( + elt=Call( + func=Name(id='generate_dataset_item', ctx=Load()), + args=[ + Name(id='cache', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='index', ctx=Load())], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='index', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Name(id='dataset_size_bytes', ctx=Load()), + op=FloorDiv(), + right=Name(id='HASH_BYTES', ctx=Load()))], + keywords=[]), + ifs=[], + is_async=0)])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash64', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='hashimoto', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header_hash', + annotation=Name(id='Hash32', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Bytes8', ctx=Load())), + arg( + arg='dataset_size', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='fetch_dataset_item', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Uint', ctx=Load())], + ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the mix digest and the final value for a header, by aggregating\n data from the full dataset.\n\n #### Parameters\n\n - `header_hash` is a valid [RLP hash] of a block header.\n - `nonce` is the propagated nonce for the given block.\n - `dataset_size` is the size of the dataset. See [`dataset_size`].\n - `fetch_dataset_item` is a function that retrieves a specific dataset item\n based on its index.\n\n #### Returns\n\n - The mix digest generated from the header hash and propagated nonce.\n - The final result obtained which will be checked for leading zeros (in\n byte representation) in correspondence with the block difficulty.\n\n [RLP hash]: ref:ethereum.rlp.rlp_hash\n [`dataset_size`]: ref:ethereum.ethash.dataset_size\n ')), + Assign( + targets=[ + Name(id='nonce_le', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Name(id='reversed', ctx=Load()), + args=[ + Name(id='nonce', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='seed_hash', ctx=Store())], + value=Call( + func=Name(id='keccak512', ctx=Load()), + args=[ + BinOp( + left=Name(id='header_hash', ctx=Load()), + op=Add(), + right=Name(id='nonce_le', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='seed_head', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U32', ctx=Load()), + attr='from_le_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='seed_hash', ctx=Load()), + slice=Slice( + upper=Constant(value=4)), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='rows', ctx=Store())], + value=BinOp( + left=Name(id='dataset_size', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=128)], + keywords=[]))), + Assign( + targets=[ + Name(id='mix', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='le_bytes_to_uint32_sequence', ctx=Load()), + args=[ + Name(id='seed_hash', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Name(id='MIX_BYTES', ctx=Load()), + op=FloorDiv(), + right=Name(id='HASH_BYTES', ctx=Load())))), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='HASHIMOTO_ACCESSES', ctx=Load())], + keywords=[]), + body=[ + AnnAssign( + target=Name(id='new_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='parent', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='fnv', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='U32', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[]), + op=BitXor(), + right=Name(id='seed_head', ctx=Load())), + Subscript( + value=Name(id='mix', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Mod(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='mix', ctx=Load())], + keywords=[])), + ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='U32', ctx=Load()), + args=[ + Name(id='rows', ctx=Load())], + keywords=[]))), + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Name(id='MIX_BYTES', ctx=Load()), + op=FloorDiv(), + right=Name(id='HASH_BYTES', ctx=Load()))], + keywords=[]), + body=[ + AugAssign( + target=Name(id='new_data', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='fetch_dataset_item', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='parent', ctx=Load())], + keywords=[])), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='j', ctx=Load())], + keywords=[]))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='mix', ctx=Store())], + value=Call( + func=Name(id='fnv_hash', ctx=Load()), + args=[ + Name(id='mix', ctx=Load()), + Name(id='new_data', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='compressed_mix', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='mix', ctx=Load())], + keywords=[]), + Constant(value=4)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compressed_mix', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Name(id='fnv', ctx=Load()), + args=[ + Call( + func=Name(id='fnv', ctx=Load()), + args=[ + Call( + func=Name(id='fnv', ctx=Load()), + args=[ + Subscript( + value=Name(id='mix', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='mix', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load())], + keywords=[]), + Subscript( + value=Name(id='mix', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=2)), + ctx=Load())], + keywords=[]), + Subscript( + value=Name(id='mix', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=3)), + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='mix_digest', ctx=Store())], + value=Call( + func=Name(id='le_uint32_sequence_to_bytes', ctx=Load()), + args=[ + Name(id='compressed_mix', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Name(id='seed_hash', ctx=Load()), + op=Add(), + right=Name(id='mix_digest', ctx=Load()))], + keywords=[])), + Return( + value=Tuple( + elts=[ + Name(id='mix_digest', ctx=Load()), + Name(id='result', ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='bytes', ctx=Load()), + Name(id='Hash32', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='hashimoto_light', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header_hash', + annotation=Name(id='Hash32', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Bytes8', ctx=Load())), + arg( + arg='cache', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='dataset_size', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Run the [`hashimoto`] algorithm by generating dataset item using the cache\n instead of loading the full dataset into main memory.\n\n #### Parameters\n\n - `header_hash` is a valid [RLP hash] of a block header.\n - `nonce` is the propagated nonce for the given block.\n - `cache` is the cache generated by [`generate_cache`].\n - `dataset_size` is the size of the dataset. See [`dataset_size`].\n\n #### Returns\n\n - The mix digest generated from the header hash and propagated nonce.\n - The final result obtained which will be checked for leading zeros (in\n byte representation) in correspondence with the block difficulty.\n\n [RLP hash]: ref:ethereum.rlp.rlp_hash\n [`dataset_size`]: ref:ethereum.ethash.dataset_size\n [`generate_cache`]: ref:ethereum.ethash.generate_cache\n [`hashimoto`]: ref:ethereum.ethash.hashimoto\n ')), + FunctionDef( + name='fetch_dataset_item', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='index', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AnnAssign( + target=Name(id='item', ctx=Store()), + annotation=Name(id='Hash64', ctx=Load()), + value=Call( + func=Name(id='generate_dataset_item', ctx=Load()), + args=[ + Name(id='cache', ctx=Load()), + Name(id='index', ctx=Load())], + keywords=[]), + simple=1), + Return( + value=Call( + func=Name(id='le_bytes_to_uint32_sequence', ctx=Load()), + args=[ + Name(id='item', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + Return( + value=Call( + func=Name(id='hashimoto', ctx=Load()), + args=[ + Name(id='header_hash', ctx=Load()), + Name(id='nonce', ctx=Load()), + Name(id='dataset_size', ctx=Load()), + Name(id='fetch_dataset_item', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='bytes', ctx=Load()), + Name(id='Hash32', ctx=Load())], + ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/ethash.v b/coq/ethereum/ethash.v new file mode 100644 index 0000000000..39aaf41d0f --- /dev/null +++ b/coq/ethereum/ethash.v @@ -0,0 +1,332 @@ +(* Generated *) +(* +Ethash is a proof-of-work algorithm designed to be [ASIC] resistant through +[memory hardness][mem-hard]. + +To achieve memory hardness, computing Ethash requires access to subsets of a +large structure. The particular subsets chosen are based on the nonce and block +header, while the set itself is changed every [`epoch`]. + +At a high level, the Ethash algorithm is as follows: + +1. Create a **seed** value, generated with [`generate_seed`] and based on the + preceding block numbers. +1. From the seed, compute a pseudorandom **cache** with [`generate_cache`]. +1. From the cache, generate a **dataset** with [`generate_dataset`]. The + dataset grows over time based on [`DATASET_EPOCH_GROWTH_SIZE`]. +1. Miners hash slices of the dataset together, which is where the memory + hardness is introduced. Verification of the proof-of-work only requires the + cache to be able to recompute a much smaller subset of the full dataset. + +[`DATASET_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.DATASET_EPOCH_GROWTH_SIZE +[`generate_dataset`]: ref:ethereum.ethash.generate_dataset +[`generate_cache`]: ref:ethereum.ethash.generate_cache +[`generate_seed`]: ref:ethereum.ethash.generate_seed +[`epoch`]: ref:ethereum.ethash.epoch +[ASIC]: https://en.wikipedia.org/wiki/Application-specific_integrated_circuit +[mem-hard]: https://en.wikipedia.org/wiki/Memory-hard_function +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. + +Definition epoch (block_number : Uint) : M Uint := + (* + Obtain the epoch number to which the block identified by `block_number` + belongs. The first epoch is numbered zero. + + An Ethash epoch is a fixed number of blocks ([`EPOCH_SIZE`]) long, during + which the dataset remains constant. At the end of each epoch, the dataset + is generated anew. See [`generate_dataset`]. + + [`EPOCH_SIZE`]: ref:ethereum.ethash.EPOCH_SIZE + [`generate_dataset`]: ref:ethereum.ethash.generate_dataset + *) + (* TODO statement *) + M.pure tt. + +Definition cache_size (block_number : Uint) : M Uint := + (* + Obtain the cache size (in bytes) of the epoch to which `block_number` + belongs. + + See [`INITIAL_CACHE_SIZE`] and [`CACHE_EPOCH_GROWTH_SIZE`] for the initial + size and linear growth rate, respectively. The cache is generated in + [`generate_cache`]. + + The actual cache size is smaller than simply multiplying + `CACHE_EPOCH_GROWTH_SIZE` by the epoch number to minimize the risk of + unintended cyclic behavior. It is defined as the highest prime number below + what linear growth would calculate. + + [`INITIAL_CACHE_SIZE`]: ref:ethereum.ethash.INITIAL_CACHE_SIZE + [`CACHE_EPOCH_GROWTH_SIZE`]: ref:ethereum.ethash.CACHE_EPOCH_GROWTH_SIZE + [`generate_cache`]: ref:ethereum.ethash.generate_cache + *) + do* M.assign "size" [[ + (* TODO expression *) in + ]] in + do* M.aug_assign [[ M.get_local ~(| "size" |) ]] [[ + M.get_local ~(| "HASH_BYTES" |) + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition dataset_size (block_number : Uint) : M Uint := + (* + Obtain the dataset size (in bytes) of the epoch to which `block_number` + belongs. + + See [`INITIAL_DATASET_SIZE`] and [`DATASET_EPOCH_GROWTH_SIZE`][ds] for the + initial size and linear growth rate, respectively. The complete dataset is + generated in [`generate_dataset`], while the slices used in verification + are generated in [`generate_dataset_item`]. + + The actual dataset size is smaller than simply multiplying + `DATASET_EPOCH_GROWTH_SIZE` by the epoch number to minimize the risk of + unintended cyclic behavior. It is defined as the highest prime number below + what linear growth would calculate. + + [`INITIAL_DATASET_SIZE`]: ref:ethereum.ethash.INITIAL_DATASET_SIZE + [ds]: ref:ethereum.ethash.DATASET_EPOCH_GROWTH_SIZE + [`generate_dataset`]: ref:ethereum.ethash.generate_dataset + [`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item + *) + do* M.assign "size" [[ + (* TODO expression *) in + ]] in + do* M.aug_assign [[ M.get_local ~(| "size" |) ]] [[ + M.get_local ~(| "MIX_BYTES" |) + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition generate_seed (block_number : Uint) : M Hash32 := + (* + Obtain the cache generation seed for the block identified by + `block_number`. See [`generate_cache`]. + + [`generate_cache`]: ref:ethereum.ethash.generate_cache + *) + do* M.assign "epoch_number" [[ + M.get_local ~(| "epoch" |) ~(| + block_number + |) in + ]] in + do* M.assign "seed" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition generate_cache (block_number : Uint) : M (* TODO type *) := + (* + Generate the cache for the block identified by `block_number`. See + [`generate_dataset`] for how the cache is used. + + The cache is generated in two steps: filling the array with a chain of + [`keccak512`] hashes, then running two rounds of Sergio Demian Lerner's + [RandMemoHash] on those bytes. + + [`keccak512`]: ref:ethereum.crypto.hash.keccak512 + [`generate_dataset`]: ref:ethereum.ethash.generate_dataset + [RandMemoHash]: http://www.hashcash.org/papers/memohash.pdf + *) + do* M.assign "seed" [[ + M.get_local ~(| "generate_seed" |) ~(| + block_number + |) in + ]] in + do* M.assign "cache_size_bytes" [[ + M.get_local ~(| "cache_size" |) ~(| + block_number + |) in + ]] in + do* M.assign "cache_size_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "cache" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition fnv (a : (* TODO type *)) (b : (* TODO type *)) : M U32 := + (* + A non-associative substitute for XOR, inspired by the [FNV] hash by Fowler, + Noll, and Vo. See [`fnv_hash`], [`generate_dataset_item`], and + [`hashimoto`]. + + Note that here we multiply the prime with the full 32-bit input, in + contrast with the [FNV-1] spec which multiplies the prime with one byte + (octet) in turn. + + [`hashimoto`]: ref:ethereum.ethash.hashimoto + [`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item + [`fnv_hash`]: ref:ethereum.ethash.fnv_hash + [FNV]: https://w.wiki/XKZ + [FNV-1]: http://www.isthe.com/chongo/tech/comp/fnv/#FNV-1 + *) + do* M.assign "result" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition fnv_hash (mix_integers : (* TODO type *)) (data : (* TODO type *)) : M (* TODO type *) := + (* + Combines `data` into `mix_integers` using [`fnv`]. See [`hashimoto`] and + [`generate_dataset_item`]. + + [`hashimoto`]: ref:ethereum.ethash.hashimoto + [`generate_dataset_item`]: ref:ethereum.ethash.generate_dataset_item + [`fnv`]: ref:ethereum.ethash.fnv + *) + (* TODO statement *) + M.pure tt. + +Definition generate_dataset_item (cache : (* TODO type *)) (index : Uint) : M Hash64 := + (* + Generate a particular dataset item 0-indexed by `index` by hashing + pseudorandomly-selected entries from `cache` together. See [`fnv`] and + [`fnv_hash`] for the digest function, [`generate_cache`] for generating + `cache`, and [`generate_dataset`] for the full dataset generation + algorithm. + + [`fnv`]: ref:ethereum.ethash.fnv + [`fnv_hash`]: ref:ethereum.ethash.fnv_hash + [`generate_dataset`]: ref:ethereum.ethash.generate_dataset + [`generate_cache`]: ref:ethereum.ethash.generate_cache + *) + do* M.assign "mix" [[ + ethereum.crypto.hash.keccak512 ~(| + M.get_field ~(| (* TODO expression *), "to_le_bytes64" |) ~(| + + |) + |) in + ]] in + do* M.assign "mix_integers" [[ + ethereum.utils.numeric.le_bytes_to_uint32_sequence ~(| + M.get_local ~(| "mix" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "mix" [[ + ethereum.crypto.hash.Hash64 ~(| + ethereum.utils.numeric.le_uint32_sequence_to_bytes ~(| + M.get_local ~(| "mix_integers" |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition generate_dataset (block_number : Uint) : M (* TODO type *) := + (* + Generate the full dataset for the block identified by `block_number`. + + This function is present only for demonstration purposes. It is not used + while validating blocks. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition hashimoto (header_hash : Hash32) (nonce : Bytes8) (dataset_size : Uint) (fetch_dataset_item : (* TODO type *)) : M (* TODO type *) := + (* + Obtain the mix digest and the final value for a header, by aggregating + data from the full dataset. + + #### Parameters + + - `header_hash` is a valid [RLP hash] of a block header. + - `nonce` is the propagated nonce for the given block. + - `dataset_size` is the size of the dataset. See [`dataset_size`]. + - `fetch_dataset_item` is a function that retrieves a specific dataset item + based on its index. + + #### Returns + + - The mix digest generated from the header hash and propagated nonce. + - The final result obtained which will be checked for leading zeros (in + byte representation) in correspondence with the block difficulty. + + [RLP hash]: ref:ethereum.rlp.rlp_hash + [`dataset_size`]: ref:ethereum.ethash.dataset_size + *) + do* M.assign "nonce_le" [[ + M.get_local ~(| "bytes" |) ~(| + M.get_local ~(| "reversed" |) ~(| + nonce + |) + |) in + ]] in + do* M.assign "seed_hash" [[ + ethereum.crypto.hash.keccak512 ~(| + (* TODO expression *) + |) in + ]] in + do* M.assign "seed_head" [[ + M.get_field ~(| ethereum_types.numeric.U32, "from_le_bytes" |) ~(| + (* TODO expression *) + |) in + ]] in + do* M.assign "rows" [[ + (* TODO expression *) in + ]] in + do* M.assign "mix" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "compressed_mix" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "mix_digest" [[ + ethereum.utils.numeric.le_uint32_sequence_to_bytes ~(| + M.get_local ~(| "compressed_mix" |) + |) in + ]] in + do* M.assign "result" [[ + ethereum.crypto.hash.keccak256 ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition hashimoto_light (header_hash : Hash32) (nonce : Bytes8) (cache : (* TODO type *)) (dataset_size : Uint) : M (* TODO type *) := + (* + Run the [`hashimoto`] algorithm by generating dataset item using the cache + instead of loading the full dataset into main memory. + + #### Parameters + + - `header_hash` is a valid [RLP hash] of a block header. + - `nonce` is the propagated nonce for the given block. + - `cache` is the cache generated by [`generate_cache`]. + - `dataset_size` is the size of the dataset. See [`dataset_size`]. + + #### Returns + + - The mix digest generated from the header hash and propagated nonce. + - The final result obtained which will be checked for leading zeros (in + byte representation) in correspondence with the block difficulty. + + [RLP hash]: ref:ethereum.rlp.rlp_hash + [`dataset_size`]: ref:ethereum.ethash.dataset_size + [`generate_cache`]: ref:ethereum.ethash.generate_cache + [`hashimoto`]: ref:ethereum.ethash.hashimoto + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/exceptions.ast b/coq/ethereum/exceptions.ast new file mode 100644 index 0000000000..f01484c057 --- /dev/null +++ b/coq/ethereum/exceptions.ast @@ -0,0 +1,59 @@ +Module( + body=[ + Expr( + value=Constant(value='\nError types common across all Ethereum forks.\n')), + ClassDef( + name='EthereumException', + bases=[ + Name(id='Exception', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Base class for all exceptions _expected_ to be thrown during normal\n operation.\n '))], + decorator_list=[]), + ClassDef( + name='InvalidBlock', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Thrown when a block being processed is found to be invalid.\n '))], + decorator_list=[]), + ClassDef( + name='InvalidTransaction', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Thrown when a transaction being processed is found to be invalid.\n '))], + decorator_list=[]), + ClassDef( + name='RLPDecodingError', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that RLP decoding failed.\n '))], + decorator_list=[]), + ClassDef( + name='RLPEncodingError', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that RLP encoding failed.\n '))], + decorator_list=[]), + ClassDef( + name='InvalidSenderError', + bases=[ + Name(id='InvalidTransaction', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Thrown when a transaction originates from an account that cannot send\n transactions.\n '))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/exceptions.v b/coq/ethereum/exceptions.v new file mode 100644 index 0000000000..ab1fc99a54 --- /dev/null +++ b/coq/ethereum/exceptions.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Error types common across all Ethereum forks. +*) + diff --git a/coq/ethereum/fork_criteria.ast b/coq/ethereum/fork_criteria.ast new file mode 100644 index 0000000000..4a39439859 --- /dev/null +++ b/coq/ethereum/fork_criteria.ast @@ -0,0 +1,539 @@ +Module( + body=[ + Expr( + value=Constant(value='\nActivation criteria for forks.\n\nMost generally, a _fork_ is a divergence in a blockchain resulting in multiple\ntips. Most forks are short lived, and can be caused by networking issues or the\nbehavior of block creators. These short-lived forks resolve themselves\naccording to the rules of the protocol, eventually settling back to a single\ntip of the chain.\n\nA second class of forks are intentionally created by changing the rules of the\nprotocol, and never resolve back to a single tip. Older software will continue\nto follow the original fork, while updated software will create and follow a\nnew fork.\n\nFor these intentional forks to succeed, all participants need to agree on\nexactly when to switch rules. The agreed upon criteria are represented by\nsubclasses of [`ForkCriteria`], like [`ByBlockNumber`] and [`ByTimestamp`]. The\nspecial type of [`Unscheduled`] is used for forks in active development that do\nnot yet have a scheduled deployment.\n\n[`ForkCriteria`]: ref:ethereum.fork_criteria.ForkCriteria\n[`ByBlockNumber`]: ref:ethereum.fork_criteria.ByBlockNumber\n[`ByTimestamp`]: ref:ethereum.fork_criteria.ByTimestamp\n[`Unscheduled`]: ref:ethereum.fork_criteria.Unscheduled\n')), + Import( + names=[ + alias(name='functools')]), + ImportFrom( + module='abc', + names=[ + alias(name='ABC'), + alias(name='abstractmethod')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Final'), + alias(name='Literal'), + alias(name='SupportsInt'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ClassDef( + name='ForkCriteria', + bases=[ + Name(id='ABC', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Abstract base class for conditions specifying when a fork activates.\n\n Subclasses override the comparison methods ([`__eq__`] and [`__lt__`]) to\n provide an ordering for forks, and override [`check`] to determine whether\n a particular block meets the activation criteria.\n\n [`__eq__`]: ref:ethereum.fork_criteria.ForkCriteria.__eq__\n [`__lt__`]: ref:ethereum.fork_criteria.ForkCriteria.__lt__\n [`check`]: ref:ethereum.fork_criteria.ForkCriteria.check\n ')), + AnnAssign( + target=Name(id='BLOCK_NUMBER', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load()), + value=Constant(value=0), + simple=1), + Expr( + value=Constant(value="\n Value representing a fork criteria based on the block's number.\n\n Used for pre-merge blocks.\n ")), + AnnAssign( + target=Name(id='TIMESTAMP', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load()), + value=Constant(value=1), + simple=1), + Expr( + value=Constant(value="\n Value representing a fork criteria based on the block's timestamp.\n\n Used for post-merge blocks.\n ")), + AnnAssign( + target=Name(id='UNSCHEDULED', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load()), + value=Constant(value=2), + simple=1), + Expr( + value=Constant(value='\n Value representing a fork criteria that will never be satisfied.\n\n Used for in-development forks.\n ')), + AnnAssign( + target=Name(id='_internal', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='int', ctx=Load()), + Name(id='int', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + FunctionDef( + name='__eq__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='other', + annotation=Name(id='object', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Equality for fork criteria.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='other', ctx=Load()), + Name(id='ForkCriteria', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='_internal', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='other', ctx=Load()), + attr='_internal', + ctx=Load())]))], + orelse=[]), + Return( + value=Name(id='NotImplemented', ctx=Load()))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='__lt__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='other', + annotation=Name(id='object', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Less-than comparison function, with earlier forks being less than later\n forks.\n\n All [`BLOCK_NUMBER`] forks come before [`TIMESTAMP`] forks, and all\n scheduled forks come before [`UNSCHEDULED`] forks.\n\n [`BLOCK_NUMBER`]: ref:ethereum.fork_criteria.ForkCriteria.BLOCK_NUMBER\n [`TIMESTAMP`]: ref:ethereum.fork_criteria.ForkCriteria.TIMESTAMP\n [`UNSCHEDULED`]: ref:ethereum.fork_criteria.ForkCriteria.UNSCHEDULED\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='other', ctx=Load()), + Name(id='ForkCriteria', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='_internal', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Attribute( + value=Name(id='other', ctx=Load()), + attr='_internal', + ctx=Load())]))], + orelse=[]), + Return( + value=Name(id='NotImplemented', ctx=Load()))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='__hash__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute a hash for this instance, so it can be stored in dictionaries.\n ')), + Return( + value=Call( + func=Name(id='hash', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_internal', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='check', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='timestamp', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether fork criteria have been met.\n\n Returns `True` when the current block meets or exceeds the criteria,\n and `False` otherwise.\n ')), + Raise( + exc=Call( + func=Name(id='NotImplementedError', ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[ + Name(id='abstractmethod', ctx=Load())], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='__repr__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n String representation of this object.\n ')), + Raise( + exc=Call( + func=Name(id='NotImplementedError', ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[ + Name(id='abstractmethod', ctx=Load())], + returns=Name(id='str', ctx=Load()))], + decorator_list=[ + Attribute( + value=Name(id='functools', ctx=Load()), + attr='total_ordering', + ctx=Load())]), + ClassDef( + name='ByBlockNumber', + bases=[ + Name(id='ForkCriteria', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Forks that occur when a specific block number has been reached.\n ')), + AnnAssign( + target=Name(id='block_number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n Number of the first block in this fork.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='block_number', + annotation=Name(id='SupportsInt', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_internal', + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='ForkCriteria', ctx=Load()), + attr='BLOCK_NUMBER', + ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[])], + ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[]), + FunctionDef( + name='check', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='timestamp', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether the block number has been reached.\n\n Returns `True` when the given `block_number` is equal to or greater\n than [`block_number`], and `False` otherwise.\n\n [`block_number`]: ref:ethereum.fork_criteria.ByBlockNumber.block_number\n ')), + Return( + value=Compare( + left=Name(id='block_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load())]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='__repr__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n String representation of this object.\n ')), + Return( + value=JoinedStr( + values=[ + Constant(value='ByBlockNumber('), + FormattedValue( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load()), + conversion=-1), + Constant(value=')')]))], + decorator_list=[], + returns=Name(id='str', ctx=Load()))], + decorator_list=[]), + ClassDef( + name='ByTimestamp', + bases=[ + Name(id='ForkCriteria', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Forks that occur when a specific timestamp has been reached.\n ')), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n First instance of time that is part of this fork.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='timestamp', + annotation=Name(id='SupportsInt', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_internal', + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='ForkCriteria', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='timestamp', ctx=Load())], + keywords=[])], + ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='timestamp', + ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='timestamp', ctx=Load())], + keywords=[]))], + decorator_list=[]), + FunctionDef( + name='check', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='timestamp', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether the timestamp has been reached.\n\n Returns `True` when the given `timestamp` is equal to or greater than\n [`timestamp`], and `False` otherwise.\n\n [`timestamp`]: ref:ethereum.fork_criteria.ByTimestamp.timestamp\n ')), + Return( + value=Compare( + left=Name(id='timestamp', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='timestamp', + ctx=Load())]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='__repr__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n String representation of this object.\n ')), + Return( + value=JoinedStr( + values=[ + Constant(value='ByTimestamp('), + FormattedValue( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='timestamp', + ctx=Load()), + conversion=-1), + Constant(value=')')]))], + decorator_list=[], + returns=Name(id='str', ctx=Load()))], + decorator_list=[]), + ClassDef( + name='Unscheduled', + bases=[ + Name(id='ForkCriteria', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Forks that have not been scheduled.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_internal', + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='ForkCriteria', ctx=Load()), + attr='UNSCHEDULED', + ctx=Load()), + Constant(value=0)], + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='timestamp', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Unscheduled forks never occur; always returns `False`.\n ')), + Return( + value=Constant(value=False))], + decorator_list=[], + returns=Subscript( + value=Name(id='Literal', ctx=Load()), + slice=Constant(value=False), + ctx=Load())), + FunctionDef( + name='__repr__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n String representation of this object.\n ')), + Return( + value=Constant(value='Unscheduled()'))], + decorator_list=[], + returns=Name(id='str', ctx=Load()))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/fork_criteria.v b/coq/ethereum/fork_criteria.v new file mode 100644 index 0000000000..0fb15ee79d --- /dev/null +++ b/coq/ethereum/fork_criteria.v @@ -0,0 +1,27 @@ +(* Generated *) +(* +Activation criteria for forks. + +Most generally, a _fork_ is a divergence in a blockchain resulting in multiple +tips. Most forks are short lived, and can be caused by networking issues or the +behavior of block creators. These short-lived forks resolve themselves +according to the rules of the protocol, eventually settling back to a single +tip of the chain. + +A second class of forks are intentionally created by changing the rules of the +protocol, and never resolve back to a single tip. Older software will continue +to follow the original fork, while updated software will create and follow a +new fork. + +For these intentional forks to succeed, all participants need to agree on +exactly when to switch rules. The agreed upon criteria are represented by +subclasses of [`ForkCriteria`], like [`ByBlockNumber`] and [`ByTimestamp`]. The +special type of [`Unscheduled`] is used for forks in active development that do +not yet have a scheduled deployment. + +[`ForkCriteria`]: ref:ethereum.fork_criteria.ForkCriteria +[`ByBlockNumber`]: ref:ethereum.fork_criteria.ByBlockNumber +[`ByTimestamp`]: ref:ethereum.fork_criteria.ByTimestamp +[`Unscheduled`]: ref:ethereum.fork_criteria.Unscheduled +*) + diff --git a/coq/ethereum/frontier/__init__.ast b/coq/ethereum/frontier/__init__.ast new file mode 100644 index 0000000000..d9ea531c30 --- /dev/null +++ b/coq/ethereum/frontier/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nFrontier is the first production-ready iteration of the Ethereum protocol.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/__init__.v b/coq/ethereum/frontier/__init__.v new file mode 100644 index 0000000000..1f5a54f0e0 --- /dev/null +++ b/coq/ethereum/frontier/__init__.v @@ -0,0 +1,6 @@ +(* Generated *) +(* +Frontier is the first production-ready iteration of the Ethereum protocol. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/frontier/blocks.ast b/coq/ethereum/frontier/blocks.ast new file mode 100644 index 0000000000..dce2db5da0 --- /dev/null +++ b/coq/ethereum/frontier/blocks.ast @@ -0,0 +1,218 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mix_digest', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='post_state', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/blocks.v b/coq/ethereum/frontier/blocks.v new file mode 100644 index 0000000000..4e022f9c09 --- /dev/null +++ b/coq/ethereum/frontier/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.frontier.fork_types. +Require ethereum.frontier.transactions. diff --git a/coq/ethereum/frontier/bloom.ast b/coq/ethereum/frontier/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/frontier/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/bloom.v b/coq/ethereum/frontier/bloom.v new file mode 100644 index 0000000000..2f8df625d6 --- /dev/null +++ b/coq/ethereum/frontier/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.frontier.blocks. +Require ethereum.frontier.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/frontier/fork.ast b/coq/ethereum/frontier/fork.ast new file mode 100644 index 0000000000..d050d74a18 --- /dev/null +++ b/coq/ethereum/frontier/fork.ast @@ -0,0 +1,2860 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.ethash', + names=[ + alias(name='dataset_size'), + alias(name='generate_cache'), + alias(name='hashimoto_light')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='create_ether'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_BASE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='Transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BLOCK_REWARD', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=5), + op=Mult(), + right=BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=18)))], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=131072)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_OMMER_DEPTH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='validate_ommers', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='chain', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_difficulty', ctx=Store())], + value=Call( + func=Name(id='calculate_block_difficulty', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_difficulty', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='validate_proof_of_work', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generate_header_hash_for_pow', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate rlp hash of the header which is to be used for Proof-of-Work\n verification.\n\n In other words, the PoW artefacts `mix_digest` and `nonce` are ignored\n while calculating this hash.\n\n A particular PoW is valid for a single hash, that hash is computed by\n this function. The `nonce` and `mix_digest` are omitted from this hash\n because they are being changed by miners in their search for a sufficient\n proof-of-work.\n\n Parameters\n ----------\n header :\n The header object for which the hash is to be generated.\n\n Returns\n -------\n hash : `Hash32`\n The PoW valid rlp hash of the passed in header.\n ')), + Assign( + targets=[ + Name(id='header_data_without_pow_artefacts', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='state_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='transactions_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='receipt_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='bloom', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='header_data_without_pow_artefacts', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='validate_proof_of_work', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the Proof of Work constraints.\n\n In order to verify that a miner's proof-of-work is valid for a block, a\n ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``\n hash function. The mix digest is a hash of the header and the nonce that\n is passed through and it confirms whether or not proof-of-work was done\n on the correct block. The result is the actual hash value of the block.\n\n Parameters\n ----------\n header :\n Header of interest.\n ")), + Assign( + targets=[ + Name(id='header_hash', ctx=Store())], + value=Call( + func=Name(id='generate_header_hash_for_pow', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache', ctx=Store())], + value=Call( + func=Name(id='generate_cache', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='mix_digest', ctx=Store()), + Name(id='result', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='hashimoto_light', ctx=Load()), + args=[ + Name(id='header_hash', ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + Name(id='cache', ctx=Load()), + Call( + func=Name(id='dataset_size', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='mix_digest', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='mix_digest', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='limit', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='limit', ctx=Load()), + op=FloorDiv(), + right=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n gas_available :\n The gas remaining in the block.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + Return( + value=Name(id='sender_address', ctx=Load()))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='post_state', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n post_state :\n The state root immediately after this transaction.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='post_state', + value=Name(id='post_state', ctx=Load())), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + Return( + value=Name(id='receipt', ctx=Load()))], + decorator_list=[], + returns=Name(id='Receipt', ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='block_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n block_difficulty :\n Difficulty of the block.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='transactions', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='tx', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='gas_available', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='gas_price', + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='difficulty', + value=Name(id='block_difficulty', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[]), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='pay_rewards', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='block_number', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='ommers', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='validate_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='block_header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the ommers mentioned in the block.\n\n An ommer block is a block that wasn't canonically added to the\n blockchain because it wasn't validated as fast as the canonical block\n but was mined at the same time.\n\n To be considered valid, the ommers must adhere to the rules defined in\n the Ethereum protocol. The maximum amount of ommers is 2 per block and\n there cannot be duplicate ommers in a block. Many of the other ommer\n constraints are listed in the in-line comments of this function.\n\n Parameters\n ----------\n ommers :\n List of ommers mentioned in the current block.\n block_header:\n The header of current block.\n chain :\n History and current state.\n ")), + Assign( + targets=[ + Name(id='block_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='block_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='ommers_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return()], + orelse=[]), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + op=Sub(), + right=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Name(id='ommer', ctx=Load()), + Name(id='ommer_parent_header', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=2)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommers_hashes', ctx=Store())], + value=ListComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + ifs=[], + is_async=0)])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[])], + keywords=[])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_canonical_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=BinOp( + left=Name(id='MAX_OMMER_DEPTH', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + ctx=Load())), + Assign( + targets=[ + Name(id='recent_canonical_block_hashes', ctx=Store())], + value=SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='recent_ommers_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + simple=1), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='recent_ommers_hashes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='recent_ommers_hashes', ctx=Load()), + attr='union', + ctx=Load()), + args=[ + SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='ommer_index', ctx=Store()), + Name(id='ommer', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='ommer_hash', ctx=Store())], + value=Subscript( + value=Name(id='ommers_hashes', ctx=Load()), + slice=Name(id='ommer_index', ctx=Load()), + ctx=Load())), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='block_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_ommers_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='ommer_age', ctx=Load())]), + Compare( + left=Name(id='ommer_age', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_OMMER_DEPTH', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='parent_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pay_rewards', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pay rewards to the block miner as well as the ommers miners.\n\n The miner of the canonical block is rewarded with the predetermined\n block reward, ``BLOCK_REWARD``, plus a variable award based off of the\n number of ommer blocks that were mined around the same time, and included\n in the canonical block's header. An ommer block is a block that wasn't\n added to the canonical blockchain because it wasn't validated as fast as\n the accepted block but was mined at the same time. Although not all blocks\n that are mined are added to the canonical chain, miners are still paid a\n reward for their efforts. This reward is called an ommer reward and is\n calculated based on the number associated with the ommer block that they\n mined.\n\n Parameters\n ----------\n state :\n Current account state.\n block_number :\n Position of the block within the chain.\n coinbase :\n Address of account which receives block reward and transaction fees.\n ommers :\n List of ommers mentioned in the current block.\n ")), + Assign( + targets=[ + Name(id='ommer_count', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='miner_reward', ctx=Store())], + value=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='ommer_count', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='miner_reward', ctx=Load())], + keywords=[])), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_number', ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='ommer_miner_reward', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Sub(), + right=Name(id='ommer_age', ctx=Load())), + op=Mult(), + right=Name(id='BLOCK_REWARD', ctx=Load())), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='ommer_miner_reward', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[])), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='v', ctx=Store()), + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=28)])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Compute the hash of a transaction used in the signature.\n\n The values that are used to compute the signing hash set the rules for a\n transaction. For example, signing over the gas sets a limit for the\n amount of money that is allowed to be pulled out of the sender's account.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_difficulty', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes difficulty of a block using its header and\n parent header.\n\n The difficulty of a block is determined by the time the block was\n created after its parent. If a block's timestamp is more than 13\n seconds after its parent block then its difficulty is set as the\n difference between the parent's difficulty and the\n ``max_adjustment_delta``. Otherwise, if the time between parent and\n child blocks is too small (under 13 seconds) then, to avoid mass\n forking, the block's difficulty is set to the sum of the delta and\n the parent's difficulty.\n\n Parameters\n ----------\n block_number :\n Block number of the block.\n block_timestamp :\n Timestamp of the block.\n parent_timestamp :\n Timestamp of the parent block.\n parent_difficulty :\n difficulty of the parent block.\n\n Returns\n -------\n difficulty : `ethereum.base_types.Uint`\n Computed difficulty for a block.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_difficulty', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2048)], + keywords=[]))), + If( + test=Compare( + left=Name(id='block_timestamp', ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='parent_timestamp', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=13)], + keywords=[]))]), + body=[ + Assign( + targets=[ + Name(id='difficulty', ctx=Store())], + value=BinOp( + left=Name(id='parent_difficulty', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='difficulty', ctx=Store())], + value=BinOp( + left=Name(id='parent_difficulty', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load())))]), + Assign( + targets=[ + Name(id='num_bomb_periods', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=100000)), + op=Sub(), + right=Constant(value=2))), + If( + test=Compare( + left=Name(id='num_bomb_periods', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='difficulty', ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Name(id='num_bomb_periods', ctx=Load())))], + orelse=[]), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='difficulty', ctx=Load()), + Name(id='MINIMUM_DIFFICULTY', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/fork.v b/coq/ethereum/frontier/fork.v new file mode 100644 index 0000000000..b917c923c5 --- /dev/null +++ b/coq/ethereum/frontier/fork.v @@ -0,0 +1,821 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.ethash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.frontier.__init__. +Require ethereum.frontier.blocks. +Require ethereum.frontier.bloom. +Require ethereum.frontier.fork_types. +Require ethereum.frontier.state. +Require ethereum.frontier.transactions. +Require ethereum.frontier.trie. +Require ethereum.frontier.utils.message. +Require ethereum.frontier.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + do* [[ M.get_local ~(| "validate_ommers" |) ~(| + M.get_field ~(| block, "ommers" |), + M.get_field ~(| block, "header" |), + chain + |) ]] in + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "difficulty" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| block, "ommers" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_difficulty" [[ + M.get_local ~(| "calculate_block_difficulty" |) ~(| + M.get_field ~(| header, "number" |), + M.get_field ~(| header, "timestamp" |), + M.get_field ~(| parent_header, "timestamp" |), + M.get_field ~(| parent_header, "difficulty" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| + header + |) ]] in + M.pure tt. + +Definition generate_header_hash_for_pow (header : Header) : M Hash32 := + (* + 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. + *) + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_proof_of_work (header : Header) : M unit := + (* + 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. + *) + do* M.assign "header_hash" [[ + M.get_local ~(| "generate_header_hash_for_pow" |) ~(| + header + |) in + ]] in + do* M.assign "cache" [[ + ethereum.ethash.generate_cache ~(| + M.get_field ~(| header, "number" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (gas_available : Uint) : M 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. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + tx + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (post_state : Bytes32) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (block_gas_limit : Uint) (block_time : U256) (block_difficulty : Uint) (transactions : (* TODO type *)) (ommers : (* TODO type *)) : M ApplyBodyOutput := + (* + 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 + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "pay_rewards" |) ~(| + state, + block_number, + coinbase, + ommers + |) ]] in + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_ommers (ommers : (* TODO type *)) (block_header : Header) (chain : BlockChain) : M unit := + (* + 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. + *) + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_canonical_blocks" [[ + (* TODO expression *) in + ]] in + do* M.assign "recent_canonical_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition pay_rewards (state : State) (block_number : Uint) (coinbase : Address) (ommers : (* TODO type *)) : M unit := + (* + 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. + *) + do* M.assign "ommer_count" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + ommers + |) + |) in + ]] in + do* M.assign "miner_reward" [[ + (* TODO expression *) in + ]] in + do* [[ state.create_ether ~(| + state, + coinbase, + M.get_local ~(| "miner_reward" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + do* M.assign "gas_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| env, "coinbase" |), + M.get_local ~(| "coinbase_balance_after_mining_fee" |) + |) ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "public_key" [[ + ethereum.crypto.elliptic_curve.secp256k1_recover ~(| + M.get_local ~(| "r" |), + M.get_local ~(| "s" |), + (* TODO expression *), + M.get_local ~(| "signing_hash" |) ~(| + tx + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition signing_hash (tx : Transaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_block_difficulty (block_number : Uint) (block_timestamp : U256) (parent_timestamp : U256) (parent_difficulty : Uint) : M Uint := + (* + Computes difficulty of a block using its header and + parent header. + + The difficulty of a block is determined by the time the block was + created after its parent. If a block's timestamp is more than 13 + seconds after its parent block then its difficulty is set as the + difference between the parent's difficulty and the + ``max_adjustment_delta``. Otherwise, if the time between parent and + child blocks is too small (under 13 seconds) then, to avoid mass + forking, the block's difficulty is set to the sum of the delta and + the parent's 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "num_bomb_periods" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/frontier/fork_types.ast b/coq/ethereum/frontier/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/frontier/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/fork_types.v b/coq/ethereum/frontier/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/frontier/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/frontier/state.ast b/coq/ethereum/frontier/state.ast new file mode 100644 index 0000000000..dce2e294a9 --- /dev/null +++ b/coq/ethereum/frontier/state.ast @@ -0,0 +1,1292 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add newly created ether to an account.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to which ether is added.\n amount:\n The amount of ether to be added to the account of interest.\n ')), + FunctionDef( + name='increase_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/state.v b/coq/ethereum/frontier/state.v new file mode 100644 index 0000000000..e4a5b7d0cb --- /dev/null +++ b/coq/ethereum/frontier/state.v @@ -0,0 +1,484 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.frontier.fork_types. +Require ethereum.frontier.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := + (* + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum/frontier/transactions.ast b/coq/ethereum/frontier/transactions.ast new file mode 100644 index 0000000000..a5cb88b981 --- /dev/null +++ b/coq/ethereum/frontier/transactions.ast @@ -0,0 +1,102 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + ClassDef( + name='Transaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/transactions.v b/coq/ethereum/frontier/transactions.v new file mode 100644 index 0000000000..b3bdb570f6 --- /dev/null +++ b/coq/ethereum/frontier/transactions.v @@ -0,0 +1,13 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.frontier.fork_types. diff --git a/coq/ethereum/frontier/trie.ast b/coq/ethereum/frontier/trie.ast new file mode 100644 index 0000000000..60b7a8fe98 --- /dev/null +++ b/coq/ethereum/frontier/trie.ast @@ -0,0 +1,1619 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.RLP`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='encoding for '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value=' is not currently implemented')])], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/trie.v b/coq/ethereum/frontier/trie.v new file mode 100644 index 0000000000..6b8953f256 --- /dev/null +++ b/coq/ethereum/frontier/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/frontier/utils/__init__.ast b/coq/ethereum/frontier/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/frontier/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/utils/__init__.v b/coq/ethereum/frontier/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/frontier/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/frontier/utils/address.ast b/coq/ethereum/frontier/utils/address.ast new file mode 100644 index 0000000000..438705ba1e --- /dev/null +++ b/coq/ethereum/frontier/utils/address.ast @@ -0,0 +1,139 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this frontier version of specification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `ethereum.frontier.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/utils/address.v b/coq/ethereum/frontier/utils/address.v new file mode 100644 index 0000000000..47863b9c36 --- /dev/null +++ b/coq/ethereum/frontier/utils/address.v @@ -0,0 +1,74 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this frontier version of specification. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.frontier.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.frontier.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/frontier/utils/hexadecimal.ast b/coq/ethereum/frontier/utils/hexadecimal.ast new file mode 100644 index 0000000000..fdeb10d705 --- /dev/null +++ b/coq/ethereum/frontier/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to Frontier\ntypes.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/utils/hexadecimal.v b/coq/ethereum/frontier/utils/hexadecimal.v new file mode 100644 index 0000000000..5bdfa980bd --- /dev/null +++ b/coq/ethereum/frontier/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to Frontier +types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.frontier.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/frontier/utils/message.ast b/coq/ethereum/frontier/utils/message.ast new file mode 100644 index 0000000000..18c350a333 --- /dev/null +++ b/coq/ethereum/frontier/utils/message.ast @@ -0,0 +1,227 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this frontier version of specification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n\n Returns\n -------\n message: `ethereum.frontier.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/utils/message.v b/coq/ethereum/frontier/utils/message.v new file mode 100644 index 0000000000..7fba7a2069 --- /dev/null +++ b/coq/ethereum/frontier/utils/message.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this frontier version of specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.frontier.fork_types. +Require ethereum.frontier.state. +Require ethereum.frontier.vm. +Require ethereum.frontier.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + + Returns + ------- + message: `ethereum.frontier.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/frontier/vm/__init__.ast b/coq/ethereum/frontier/vm/__init__.ast new file mode 100644 index 0000000000..4784ad609c --- /dev/null +++ b/coq/ethereum/frontier/vm/__init__.ast @@ -0,0 +1,358 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State')], + level=2), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/__init__.v b/coq/ethereum/frontier/vm/__init__.v new file mode 100644 index 0000000000..42de0686a7 --- /dev/null +++ b/coq/ethereum/frontier/vm/__init__.v @@ -0,0 +1,65 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.frontier.blocks. +Require ethereum.frontier.fork_types. +Require ethereum.frontier.state. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/frontier/vm/exceptions.ast b/coq/ethereum/frontier/vm/exceptions.ast new file mode 100644 index 0000000000..3194c3c232 --- /dev/null +++ b/coq/ethereum/frontier/vm/exceptions.ast @@ -0,0 +1,125 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/exceptions.v b/coq/ethereum/frontier/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/frontier/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/frontier/vm/gas.ast b/coq/ethereum/frontier/vm/gas.ast new file mode 100644 index 0000000000..675fef92a5 --- /dev/null +++ b/coq/ethereum/frontier/vm/gas.ast @@ -0,0 +1,759 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists')], + level=2), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXTERNAL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BALANCE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=40)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='REFUND_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=24000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount for executing Opcodes `CALL` and `CALLCODE`.\n\n Parameters\n ----------\n state :\n The current state.\n gas :\n The amount of gas provided to the message-call.\n to:\n The address of the recipient account.\n value:\n The amount of `ETH` that needs to be transferred.\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='gas', ctx=Load())), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))), + Assign( + targets=[ + Name(id='stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Name(id='gas', ctx=Load()), + orelse=BinOp( + left=Name(id='GAS_CALL_STIPEND', ctx=Load()), + op=Add(), + right=Name(id='gas', ctx=Load())))), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + Name(id='cost', ctx=Load()), + Name(id='stipend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/gas.v b/coq/ethereum/frontier/vm/gas.v new file mode 100644 index 0000000000..0555940bcd --- /dev/null +++ b/coq/ethereum/frontier/vm/gas.v @@ -0,0 +1,149 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.frontier.fork_types. +Require ethereum.frontier.state. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (state : State) (gas : Uint) (to : Address) (value : U256) : M MessageCallGas := + (* + Calculates the gas amount for executing Opcodes `CALL` and `CALLCODE`. + + Parameters + ---------- + state : + The current state. + gas : + The amount of gas provided to the message-call. + to: + The address of the recipient account. + value: + The amount of `ETH` that needs to be transferred. + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/frontier/vm/instructions/__init__.ast b/coq/ethereum/frontier/vm/instructions/__init__.ast new file mode 100644 index 0000000000..edf50bae4b --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/__init__.ast @@ -0,0 +1,1636 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='DIFFICULTY', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIFFICULTY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/instructions/__init__.v b/coq/ethereum/frontier/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/frontier/vm/instructions/arithmetic.ast b/coq/ethereum/frontier/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/instructions/arithmetic.v b/coq/ethereum/frontier/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..68ae8e4ef3 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/frontier/vm/instructions/bitwise.ast b/coq/ethereum/frontier/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..73dc9f4a45 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/bitwise.ast @@ -0,0 +1,418 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/instructions/bitwise.v b/coq/ethereum/frontier/vm/instructions/bitwise.v new file mode 100644 index 0000000000..747ad4ded7 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/bitwise.v @@ -0,0 +1,196 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/frontier/vm/instructions/block.ast b/coq/ethereum/frontier/vm/instructions/block.ast new file mode 100644 index 0000000000..cc66857e82 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/block.ast @@ -0,0 +1,437 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's difficulty onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/instructions/block.v b/coq/ethereum/frontier/vm/instructions/block.v new file mode 100644 index 0000000000..53883c35b7 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/block.v @@ -0,0 +1,213 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition difficulty (evm : Evm) : M unit := + (* + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/frontier/vm/instructions/comparison.ast b/coq/ethereum/frontier/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/instructions/comparison.v b/coq/ethereum/frontier/vm/instructions/comparison.v new file mode 100644 index 0000000000..b8fc0d99b1 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/frontier/vm/instructions/control_flow.ast b/coq/ethereum/frontier/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/instructions/control_flow.v b/coq/ethereum/frontier/vm/instructions/control_flow.v new file mode 100644 index 0000000000..8d774a9866 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.exceptions. +Require ethereum.frontier.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/frontier/vm/instructions/environment.ast b/coq/ethereum/frontier/vm/instructions/environment.ast new file mode 100644 index 0000000000..15f88ad9cc --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/environment.ast @@ -0,0 +1,1199 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BALANCE'), + alias(name='GAS_BASE'), + alias(name='GAS_COPY'), + alias(name='GAS_EXTERNAL'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BALANCE', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_EXTERNAL', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_EXTERNAL', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/instructions/environment.v b/coq/ethereum/frontier/vm/instructions/environment.v new file mode 100644 index 0000000000..cf2f8aad3f --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/environment.v @@ -0,0 +1,552 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.frontier.state. +Require ethereum.frontier.utils.address. +Require ethereum.frontier.vm.memory. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BALANCE + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_EXTERNAL + |) ]] in + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/frontier/vm/instructions/keccak.ast b/coq/ethereum/frontier/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/instructions/keccak.v b/coq/ethereum/frontier/vm/instructions/keccak.v new file mode 100644 index 0000000000..ceca13d7a4 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.memory. +Require ethereum.frontier.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/frontier/vm/instructions/log.ast b/coq/ethereum/frontier/vm/instructions/log.ast new file mode 100644 index 0000000000..d3bf292c44 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/log.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/instructions/log.v b/coq/ethereum/frontier/vm/instructions/log.v new file mode 100644 index 0000000000..671f8d43ab --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/log.v @@ -0,0 +1,77 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.frontier.blocks. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.memory. +Require ethereum.frontier.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/frontier/vm/instructions/memory.ast b/coq/ethereum/frontier/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/instructions/memory.v b/coq/ethereum/frontier/vm/instructions/memory.v new file mode 100644 index 0000000000..fdb712b2f6 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.memory. +Require ethereum.frontier.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/frontier/vm/instructions/stack.ast b/coq/ethereum/frontier/vm/instructions/stack.ast new file mode 100644 index 0000000000..95cfc0b6cf --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/stack.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/instructions/stack.v b/coq/ethereum/frontier/vm/instructions/stack.v new file mode 100644 index 0000000000..6c8cd9cef5 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/stack.v @@ -0,0 +1,153 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.exceptions. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/frontier/vm/instructions/storage.ast b/coq/ethereum/frontier/vm/instructions/storage.ast new file mode 100644 index 0000000000..7ce9b2f17f --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/storage.ast @@ -0,0 +1,278 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_SLOAD', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_UPDATE', ctx=Load()))]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/instructions/storage.v b/coq/ethereum/frontier/vm/instructions/storage.v new file mode 100644 index 0000000000..b9763cbd32 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/storage.v @@ -0,0 +1,108 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.frontier.state. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_SLOAD + |) ]] in + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/frontier/vm/instructions/system.ast b/coq/ethereum/frontier/vm/instructions/system.ast new file mode 100644 index 0000000000..c5d8781d80 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/system.ast @@ -0,0 +1,1663 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CREATE'), + alias(name='GAS_ZERO'), + alias(name='REFUND_SELF_DESTRUCT'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])])]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_ZERO', ctx=Load())), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='refunded_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load())), + While( + test=Compare( + left=Name(id='parent_evm', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='refunded_accounts', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='originator', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='refunded_accounts', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='REFUND_SELF_DESTRUCT', ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/instructions/system.v b/coq/ethereum/frontier/vm/instructions/system.v new file mode 100644 index 0000000000..d3eb2606a2 --- /dev/null +++ b/coq/ethereum/frontier/vm/instructions/system.v @@ -0,0 +1,411 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.frontier.fork_types. +Require ethereum.frontier.state. +Require ethereum.frontier.utils.address. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.memory. +Require ethereum.frontier.vm.stack. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "create_message_gas" [[ + M.get_field ~(| evm, "gas_left" |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "gas" |), + M.get_local ~(| "to" |), + M.get_local ~(| "value" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "gas" |), + M.get_local ~(| "to" |), + M.get_local ~(| "value" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_ZERO in + ]] in + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "refunded_accounts" [[ + M.get_field ~(| evm, "accounts_to_delete" |) in + ]] in + do* M.assign "parent_evm" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "parent_evm" |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO assignment *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/frontier/vm/interpreter.ast b/coq/ethereum/frontier/vm/interpreter.ast new file mode 100644 index 0000000000..9a27502c41 --- /dev/null +++ b/coq/ethereum/frontier/vm/interpreter.ast @@ -0,0 +1,947 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidOpcode'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.frontier.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b''))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[]))], + finalbody=[]), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.frontier.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='error', + value=Constant(value=None))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/interpreter.v b/coq/ethereum/frontier/vm/interpreter.v new file mode 100644 index 0000000000..3464c3e511 --- /dev/null +++ b/coq/ethereum/frontier/vm/interpreter.v @@ -0,0 +1,165 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.frontier.blocks. +Require ethereum.frontier.fork_types. +Require ethereum.frontier.state. +Require ethereum.frontier.vm. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.precompiled_contracts.mapping. +Require ethereum.frontier.vm.__init__. +Require ethereum.frontier.vm.exceptions. +Require ethereum.frontier.vm.instructions. +Require ethereum.frontier.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.frontier.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.frontier.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/frontier/vm/memory.ast b/coq/ethereum/frontier/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/frontier/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/memory.v b/coq/ethereum/frontier/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/frontier/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/__init__.ast b/coq/ethereum/frontier/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..2ac4916772 --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,52 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/__init__.v b/coq/ethereum/frontier/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..b96bd9e8b1 --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.frontier.utils.hexadecimal. diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/frontier/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/frontier/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..d210f88bdb --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.frontier.vm. +Require ethereum.frontier.vm.gas. +Require ethereum.frontier.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/identity.ast b/coq/ethereum/frontier/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/identity.v b/coq/ethereum/frontier/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..84c32782d5 --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.frontier.vm. +Require ethereum.frontier.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/mapping.ast b/coq/ethereum/frontier/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..de162645ff --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,65 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/mapping.v b/coq/ethereum/frontier/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..4b4e1ee90b --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/mapping.v @@ -0,0 +1,22 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.frontier.fork_types. +Require ethereum.frontier.vm.precompiled_contracts.__init__. +Require ethereum.frontier.vm.precompiled_contracts.ecrecover. +Require ethereum.frontier.vm.precompiled_contracts.identity. +Require ethereum.frontier.vm.precompiled_contracts.ripemd160. +Require ethereum.frontier.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/frontier/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/frontier/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/sha256.ast b/coq/ethereum/frontier/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/precompiled_contracts/sha256.v b/coq/ethereum/frontier/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/frontier/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/frontier/vm/runtime.ast b/coq/ethereum/frontier/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/frontier/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/runtime.v b/coq/ethereum/frontier/vm/runtime.v new file mode 100644 index 0000000000..779eae3568 --- /dev/null +++ b/coq/ethereum/frontier/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.frontier.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/frontier/vm/stack.ast b/coq/ethereum/frontier/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/frontier/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/frontier/vm/stack.v b/coq/ethereum/frontier/vm/stack.v new file mode 100644 index 0000000000..be1ae63575 --- /dev/null +++ b/coq/ethereum/frontier/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.frontier.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/genesis.ast b/coq/ethereum/genesis.ast new file mode 100644 index 0000000000..0e9873aea8 --- /dev/null +++ b/coq/ethereum/genesis.ast @@ -0,0 +1,1107 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTypes and functions for beginning a new chain.\n\n_Genesis_ is the term for the beginning of a new chain, and so a genesis block\nis a block with no parent (its [`parent_hash`] is all zeros.)\n\nThe genesis configuration for a chain is specified with a\n[`GenesisConfiguration`], and genesis blocks are created with\n[`add_genesis_block`].\n\n[`parent_hash`]: ref:ethereum.frontier.blocks.Header.parent_hash\n[`GenesisConfiguration`]: ref:ethereum.genesis.GenesisConfiguration\n[`add_genesis_block`]: ref:ethereum.genesis.add_genesis_block\n')), + Import( + names=[ + alias(name='json')]), + Import( + names=[ + alias(name='pkgutil')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Any'), + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='Type'), + alias(name='TypeVar')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32'), + alias(name='FixedBytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum', + names=[ + alias(name='rlp')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='ethereum.utils', + names=[ + alias(name='has_field')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes'), + alias(name='hex_to_bytes8'), + alias(name='hex_to_bytes32'), + alias(name='hex_to_u256'), + alias(name='hex_to_uint')], + level=0), + ClassDef( + name='GenesisConfiguration', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Configuration for the first block of an Ethereum chain.\n\n Specifies the allocation of ether set out in the pre-sale, and some of\n the fields of the genesis block.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + Expr( + value=Constant(value="\n Discriminant between diverged blockchains; `1` for Ethereum's main network.\n ")), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n See [`difficulty`] (and subsequent forks.)\n\n [`difficulty`]: ref:ethereum.frontier.blocks.Header.difficulty\n ')), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n See [`extra_data`] (and subsequent forks.)\n\n [`extra_data`]: ref:ethereum.frontier.blocks.Header.extra_data\n ')), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n See [`gas_limit`] (and subsequent forks.)\n\n [`gas_limit`]: ref:ethereum.frontier.blocks.Header.gas_limit\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n See [`nonce`] (and subsequent forks.)\n\n [`nonce`]: ref:ethereum.frontier.blocks.Header.nonce\n ')), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n See [`timestamp`] (and subsequent forks.)\n\n [`timestamp`]: ref:ethereum.frontier.blocks.Header.timestamp\n ')), + AnnAssign( + target=Name(id='initial_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='str', ctx=Load()), + Name(id='Dict', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n State of the blockchain at genesis.\n '))], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='get_genesis_configuration', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='genesis_file', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read a genesis configuration from the given JSON file path.\n\n The genesis file should be present in the `assets` directory.\n ')), + Assign( + targets=[ + Name(id='genesis_path', ctx=Store())], + value=JoinedStr( + values=[ + Constant(value='assets/'), + FormattedValue( + value=Name(id='genesis_file', ctx=Load()), + conversion=-1)])), + Assign( + targets=[ + Name(id='genesis_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='pkgutil', ctx=Load()), + attr='get_data', + ctx=Load()), + args=[ + Constant(value='ethereum'), + Name(id='genesis_path', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='genesis_bytes', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Unable to read genesis from `'), + FormattedValue( + value=Name(id='genesis_path', ctx=Load()), + conversion=-1), + Constant(value='`')])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='genesis_data', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='loads', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='genesis_bytes', ctx=Load()), + attr='decode', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='GenesisConfiguration', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='chain_id', + value=Call( + func=Name(id='U64', ctx=Load()), + args=[ + Subscript( + value=Subscript( + value=Name(id='genesis_data', ctx=Load()), + slice=Constant(value='config'), + ctx=Load()), + slice=Constant(value='chainId'), + ctx=Load())], + keywords=[])), + keyword( + arg='difficulty', + value=Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Subscript( + value=Name(id='genesis_data', ctx=Load()), + slice=Constant(value='difficulty'), + ctx=Load())], + keywords=[])), + keyword( + arg='extra_data', + value=Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='genesis_data', ctx=Load()), + slice=Constant(value='extraData'), + ctx=Load())], + keywords=[])), + keyword( + arg='gas_limit', + value=Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Subscript( + value=Name(id='genesis_data', ctx=Load()), + slice=Constant(value='gasLimit'), + ctx=Load())], + keywords=[])), + keyword( + arg='nonce', + value=Call( + func=Name(id='hex_to_bytes8', ctx=Load()), + args=[ + Subscript( + value=Name(id='genesis_data', ctx=Load()), + slice=Constant(value='nonce'), + ctx=Load())], + keywords=[])), + keyword( + arg='timestamp', + value=Call( + func=Name(id='hex_or_base_10_str_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='genesis_data', ctx=Load()), + slice=Constant(value='timestamp'), + ctx=Load())], + keywords=[])), + keyword( + arg='initial_accounts', + value=Subscript( + value=Name(id='genesis_data', ctx=Load()), + slice=Constant(value='alloc'), + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='GenesisConfiguration', ctx=Load())), + FunctionDef( + name='hex_or_base_10_str_to_u256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='balance', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a string in either hexadecimal or base-10 to a `U256`.\n ')), + If( + test=Call( + func=Attribute( + value=Name(id='balance', ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Constant(value='0x')], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Name(id='balance', ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='balance', ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + Assign( + targets=[ + Name(id='AddressT', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='AddressT')], + keywords=[ + keyword( + arg='bound', + value=Name(id='FixedBytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='AccountT', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='AccountT')], + keywords=[])), + Assign( + targets=[ + Name(id='StateT', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='StateT')], + keywords=[])), + Assign( + targets=[ + Name(id='TrieT', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='TrieT')], + keywords=[])), + Assign( + targets=[ + Name(id='BloomT', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='BloomT')], + keywords=[])), + Assign( + targets=[ + Name(id='HeaderT', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='HeaderT')], + keywords=[])), + Assign( + targets=[ + Name(id='BlockT', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='BlockT')], + keywords=[])), + ClassDef( + name='GenesisFork', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='AddressT', ctx=Load()), + Name(id='AccountT', ctx=Load()), + Name(id='StateT', ctx=Load()), + Name(id='TrieT', ctx=Load()), + Name(id='BloomT', ctx=Load()), + Name(id='HeaderT', ctx=Load()), + Name(id='BlockT', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Pointers to the various types and functions required to build a genesis\n block.\n ')), + AnnAssign( + target=Name(id='Address', ctx=Store()), + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='FixedBytes', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='Account', ctx=Store()), + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Name(id='bytes', ctx=Load())], + ctx=Load()), + Name(id='AccountT', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='Trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='bool', ctx=Load()), + Name(id='object', ctx=Load())], + ctx=Load()), + Name(id='TrieT', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='Bloom', ctx=Store()), + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='FixedBytes', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='Header', ctx=Store()), + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='HeaderT', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='Block', ctx=Store()), + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='BlockT', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='hex_to_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='str', ctx=Load())], + ctx=Load()), + Name(id='AddressT', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='set_account', ctx=Store()), + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='StateT', ctx=Load()), + Name(id='AddressT', ctx=Load()), + Name(id='AccountT', ctx=Load())], + ctx=Load()), + Name(id='object', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='set_storage', ctx=Store()), + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='StateT', ctx=Load()), + Name(id='AddressT', ctx=Load()), + Name(id='Bytes32', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + Name(id='object', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='StateT', ctx=Load())], + ctx=Load()), + Name(id='Hash32', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='root', ctx=Store()), + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='TrieT', ctx=Load())], + ctx=Load()), + Name(id='object', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='add_genesis_block', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hardfork', + annotation=Subscript( + value=Name(id='GenesisFork', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='AddressT', ctx=Load()), + Name(id='AccountT', ctx=Load()), + Name(id='StateT', ctx=Load()), + Name(id='TrieT', ctx=Load()), + Name(id='BloomT', ctx=Load()), + Name(id='HeaderT', ctx=Load()), + Name(id='BlockT', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='chain', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='genesis', + annotation=Name(id='GenesisConfiguration', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the genesis block to an empty blockchain.\n\n The genesis block is an entirely sui generis block (unique) that is not\n governed by the general rules applying to all other Ethereum blocks.\n Instead, the only consensus requirement is that it must be identical to\n the block added by this function.\n\n The mainnet genesis configuration was originally created using the\n `mk_genesis_block.py` script. It is long since defunct, but is still\n available at .\n\n The initial state is populated with balances based on the Ethereum presale\n that happened on the Bitcoin blockchain. Additional ether worth 1.98% of\n the presale was given to the foundation.\n\n The `state_root` is set to the root of the initial state. The `gas_limit`\n and `difficulty` are set to suitable starting values. In particular the\n low gas limit made sending transactions impossible in the early stages of\n Frontier.\n\n The `nonce` field is `0x42` referencing Douglas Adams\' "HitchHiker\'s Guide\n to the Galaxy".\n\n The `extra_data` field contains the hash of block `1028201` on\n the pre-launch Olympus testnet. The creation of block `1028201` on Olympus\n marked the "starting gun" for Ethereum block creation. Including its hash\n in the genesis block ensured a fair launch of the Ethereum mining process.\n\n The remaining fields are set to appropriate default values.\n\n On testnets the genesis configuration usually allocates 1 wei to addresses\n `0x00` to `0xFF` to avoid edge cases around precompiles being created or\n cleared (by [EIP-161]).\n\n [EIP-161]: https://eips.ethereum.org/EIPS/eip-161\n ')), + AnnAssign( + target=Name(id='Address', ctx=Store()), + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='FixedBytes', ctx=Load()), + ctx=Load()), + value=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Address', + ctx=Load()), + simple=1), + Assert( + test=Call( + func=Name(id='issubclass', ctx=Load()), + args=[ + Name(id='Address', ctx=Load()), + Name(id='FixedBytes', ctx=Load())], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='hex_address', ctx=Store()), + Name(id='account', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='genesis', ctx=Load()), + attr='initial_accounts', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='hex_to_address', + ctx=Load()), + args=[ + Name(id='hex_address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='set_account', + ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Account', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='account', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='nonce'), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]), + Call( + func=Name(id='hex_or_base_10_str_to_u256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='account', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='balance'), + Constant(value=0)], + keywords=[])], + keywords=[]), + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='account', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='code'), + Constant(value='0x')], + keywords=[])], + keywords=[])], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='key', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='account', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='storage'), + Dict(keys=[], values=[])], + keywords=[]), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='set_storage', + ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='hex_to_bytes32', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Name(id='fields', ctx=Store())], + value=Dict( + keys=[ + Constant(value='parent_hash'), + Constant(value='ommers_hash'), + Constant(value='coinbase'), + Constant(value='state_root'), + Constant(value='transactions_root'), + Constant(value='receipt_root'), + Constant(value='bloom'), + Constant(value='difficulty'), + Constant(value='number'), + Constant(value='gas_limit'), + Constant(value='gas_used'), + Constant(value='timestamp'), + Constant(value='extra_data'), + Constant(value='nonce')], + values=[ + Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=32))], + keywords=[]), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Tuple(elts=[], ctx=Load())], + keywords=[]), + Call( + func=Name(id='Address', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='Address', ctx=Load()), + attr='LENGTH', + ctx=Load()))], + keywords=[]), + Call( + func=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='state_root', + ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]), + Call( + func=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='root', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Trie', + ctx=Load()), + args=[ + Constant(value=False), + Constant(value=None)], + keywords=[])], + keywords=[]), + Call( + func=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='root', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Trie', + ctx=Load()), + args=[ + Constant(value=False), + Constant(value=None)], + keywords=[])], + keywords=[]), + Call( + func=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Bloom', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + Attribute( + value=Name(id='genesis', ctx=Load()), + attr='difficulty', + ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Name(id='genesis', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Name(id='genesis', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='genesis', ctx=Load()), + attr='extra_data', + ctx=Load()), + Attribute( + value=Name(id='genesis', ctx=Load()), + attr='nonce', + ctx=Load())])), + If( + test=Call( + func=Name(id='has_field', ctx=Load()), + args=[ + Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Header', + ctx=Load()), + Constant(value='mix_digest')], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='fields', ctx=Load()), + slice=Constant(value='mix_digest'), + ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=32))], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Name(id='fields', ctx=Load()), + slice=Constant(value='prev_randao'), + ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=32))], + keywords=[]))]), + If( + test=Call( + func=Name(id='has_field', ctx=Load()), + args=[ + Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Header', + ctx=Load()), + Constant(value='base_fee_per_gas')], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='fields', ctx=Load()), + slice=Constant(value='base_fee_per_gas'), + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=9))], + keywords=[]))], + orelse=[]), + If( + test=Call( + func=Name(id='has_field', ctx=Load()), + args=[ + Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Header', + ctx=Load()), + Constant(value='withdrawals_root')], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='fields', ctx=Load()), + slice=Constant(value='withdrawals_root'), + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='root', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Trie', + ctx=Load()), + args=[ + Constant(value=False), + Constant(value=None)], + keywords=[])], + keywords=[]))], + orelse=[]), + If( + test=Call( + func=Name(id='has_field', ctx=Load()), + args=[ + Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Header', + ctx=Load()), + Constant(value='blob_gas_used')], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='fields', ctx=Load()), + slice=Constant(value='blob_gas_used'), + ctx=Store())], + value=Call( + func=Name(id='U64', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + If( + test=Call( + func=Name(id='has_field', ctx=Load()), + args=[ + Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Header', + ctx=Load()), + Constant(value='excess_blob_gas')], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='fields', ctx=Load()), + slice=Constant(value='excess_blob_gas'), + ctx=Store())], + value=Call( + func=Name(id='U64', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + If( + test=Call( + func=Name(id='has_field', ctx=Load()), + args=[ + Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Header', + ctx=Load()), + Constant(value='parent_beacon_block_root')], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='fields', ctx=Load()), + slice=Constant(value='parent_beacon_block_root'), + ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=32))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='genesis_header', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Header', + ctx=Load()), + args=[], + keywords=[ + keyword( + value=Name(id='fields', ctx=Load()))])), + Assign( + targets=[ + Name(id='block_fields', ctx=Store())], + value=Dict( + keys=[ + Constant(value='header'), + Constant(value='transactions'), + Constant(value='ommers')], + values=[ + Name(id='genesis_header', ctx=Load()), + Tuple(elts=[], ctx=Load()), + Tuple(elts=[], ctx=Load())])), + If( + test=Call( + func=Name(id='has_field', ctx=Load()), + args=[ + Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Block', + ctx=Load()), + Constant(value='withdrawals')], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='block_fields', ctx=Load()), + slice=Constant(value='withdrawals'), + ctx=Store())], + value=Tuple(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='genesis_block', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='hardfork', ctx=Load()), + attr='Block', + ctx=Load()), + args=[], + keywords=[ + keyword( + value=Name(id='block_fields', ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='genesis_block', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='chain_id', + ctx=Store())], + value=Attribute( + value=Name(id='genesis', ctx=Load()), + attr='chain_id', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/genesis.v b/coq/ethereum/genesis.v new file mode 100644 index 0000000000..87553b04e5 --- /dev/null +++ b/coq/ethereum/genesis.v @@ -0,0 +1,119 @@ +(* Generated *) +(* +Types and functions for beginning a new chain. + +_Genesis_ is the term for the beginning of a new chain, and so a genesis block +is a block with no parent (its [`parent_hash`] is all zeros.) + +The genesis configuration for a chain is specified with a +[`GenesisConfiguration`], and genesis blocks are created with +[`add_genesis_block`]. + +[`parent_hash`]: ref:ethereum.frontier.blocks.Header.parent_hash +[`GenesisConfiguration`]: ref:ethereum.genesis.GenesisConfiguration +[`add_genesis_block`]: ref:ethereum.genesis.add_genesis_block +*) + + +Definition get_genesis_configuration (genesis_file : str) : M GenesisConfiguration := + (* + Read a genesis configuration from the given JSON file path. + + The genesis file should be present in the `assets` directory. + *) + do* M.assign "genesis_path" [[ + (* TODO expression *) in + ]] in + do* M.assign "genesis_bytes" [[ + M.get_field ~(| M.get_local ~(| "pkgutil" |), "get_data" |) ~(| + (* TODO constant *), + M.get_local ~(| "genesis_path" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "genesis_data" [[ + M.get_field ~(| M.get_local ~(| "json" |), "loads" |) ~(| + M.get_field ~(| M.get_local ~(| "genesis_bytes" |), "decode" |) ~(| + + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition hex_or_base_10_str_to_u256 (balance : str) : M U256 := + (* + Convert a string in either hexadecimal or base-10 to a `U256`. + *) + (* TODO statement *) + M.pure tt. + +Definition add_genesis_block (hardfork : (* TODO type *)) (chain : Any) (genesis : GenesisConfiguration) : M unit := + (* + Adds the genesis block to an empty blockchain. + + The genesis block is an entirely sui generis block (unique) that is not + governed by the general rules applying to all other Ethereum blocks. + Instead, the only consensus requirement is that it must be identical to + the block added by this function. + + The mainnet genesis configuration was originally created using the + `mk_genesis_block.py` script. It is long since defunct, but is still + available at . + + The initial state is populated with balances based on the Ethereum presale + that happened on the Bitcoin blockchain. Additional ether worth 1.98% of + the presale was given to the foundation. + + The `state_root` is set to the root of the initial state. The `gas_limit` + and `difficulty` are set to suitable starting values. In particular the + low gas limit made sending transactions impossible in the early stages of + Frontier. + + The `nonce` field is `0x42` referencing Douglas Adams' "HitchHiker's Guide + to the Galaxy". + + The `extra_data` field contains the hash of block `1028201` on + the pre-launch Olympus testnet. The creation of block `1028201` on Olympus + marked the "starting gun" for Ethereum block creation. Including its hash + in the genesis block ensured a fair launch of the Ethereum mining process. + + The remaining fields are set to appropriate default values. + + On testnets the genesis configuration usually allocates 1 wei to addresses + `0x00` to `0xFF` to avoid edge cases around precompiles being created or + cleared (by [EIP-161]). + + [EIP-161]: https://eips.ethereum.org/EIPS/eip-161 + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "fields" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "genesis_header" [[ + M.get_field ~(| hardfork, "Header" |) ~(| + + |) in + ]] in + do* M.assign "block_fields" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "genesis_block" [[ + M.get_field ~(| hardfork, "Block" |) ~(| + + |) in + ]] in + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + M.get_local ~(| "genesis_block" |) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/__init__.ast b/coq/ethereum/gray_glacier/__init__.ast new file mode 100644 index 0000000000..08444cb52d --- /dev/null +++ b/coq/ethereum/gray_glacier/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe Gray Glacier fork delays the difficulty bomb. There are no other changes\nin this fork.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=15050000)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/__init__.v b/coq/ethereum/gray_glacier/__init__.v new file mode 100644 index 0000000000..42f5c355fb --- /dev/null +++ b/coq/ethereum/gray_glacier/__init__.v @@ -0,0 +1,7 @@ +(* Generated *) +(* +The Gray Glacier fork delays the difficulty bomb. There are no other changes +in this fork. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/gray_glacier/blocks.ast b/coq/ethereum/gray_glacier/blocks.ast new file mode 100644 index 0000000000..06837ea5d6 --- /dev/null +++ b/coq/ethereum/gray_glacier/blocks.ast @@ -0,0 +1,230 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='LegacyTransaction')], + level=1), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mix_digest', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='succeeded', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/blocks.v b/coq/ethereum/gray_glacier/blocks.v new file mode 100644 index 0000000000..c51b2bf575 --- /dev/null +++ b/coq/ethereum/gray_glacier/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.gray_glacier.fork_types. +Require ethereum.gray_glacier.transactions. diff --git a/coq/ethereum/gray_glacier/bloom.ast b/coq/ethereum/gray_glacier/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/gray_glacier/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/bloom.v b/coq/ethereum/gray_glacier/bloom.v new file mode 100644 index 0000000000..1c35fb218b --- /dev/null +++ b/coq/ethereum/gray_glacier/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.gray_glacier.blocks. +Require ethereum.gray_glacier.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/exceptions.ast b/coq/ethereum/gray_glacier/exceptions.ast new file mode 100644 index 0000000000..a61ee25448 --- /dev/null +++ b/coq/ethereum/gray_glacier/exceptions.ast @@ -0,0 +1,72 @@ +Module( + body=[ + Expr( + value=Constant(value='\nExceptions specific to this fork.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Final')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidTransaction')], + level=0), + ClassDef( + name='TransactionTypeError', + bases=[ + Name(id='InvalidTransaction', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Unknown [EIP-2718] transaction type byte.\n\n [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718\n ')), + AnnAssign( + target=Name(id='transaction_type', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n The type byte of the transaction that caused the error.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='transaction_type', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='unknown transaction type `'), + FormattedValue( + value=Name(id='transaction_type', ctx=Load()), + conversion=-1), + Constant(value='`')])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='transaction_type', + ctx=Store())], + value=Name(id='transaction_type', ctx=Load()))], + decorator_list=[])], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/exceptions.v b/coq/ethereum/gray_glacier/exceptions.v new file mode 100644 index 0000000000..9a313f6d0e --- /dev/null +++ b/coq/ethereum/gray_glacier/exceptions.v @@ -0,0 +1,7 @@ +(* Generated *) +(* +Exceptions specific to this fork. +*) + +Require typing. +Require ethereum.exceptions. diff --git a/coq/ethereum/gray_glacier/fork.ast b/coq/ethereum/gray_glacier/fork.ast new file mode 100644 index 0000000000..892a4f7e22 --- /dev/null +++ b/coq/ethereum/gray_glacier/fork.ast @@ -0,0 +1,3991 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.ethash', + names=[ + alias(name='dataset_size'), + alias(name='generate_cache'), + alias(name='hashimoto_light')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty'), + alias(name='create_ether'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_ACCESS_LIST_ADDRESS_COST'), + alias(name='TX_ACCESS_LIST_STORAGE_KEY_COST'), + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='AccessListTransaction'), + alias(name='FeeMarketTransaction'), + alias(name='LegacyTransaction'), + alias(name='Transaction'), + alias(name='decode_transaction'), + alias(name='encode_transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BLOCK_REWARD', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=18)))], + keywords=[])), + Assign( + targets=[ + Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='ELASTICITY_MULTIPLIER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=131072)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_OMMER_DEPTH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='BOMB_DELAY_BLOCKS', ctx=Store())], + value=Constant(value=11400000)), + Assign( + targets=[ + Name(id='EMPTY_OMMER_HASH', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List(elts=[], ctx=Load())], + keywords=[])], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='validate_ommers', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='chain', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='chain', ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_base_fee_per_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the base fee per gas for the block.\n\n Parameters\n ----------\n block_gas_limit :\n Gas limit of the block for which the base fee is being calculated.\n parent_gas_limit :\n Gas limit of the parent block.\n parent_gas_used :\n Gas used in the parent block.\n parent_base_fee_per_gas :\n Base fee per gas of the parent block.\n\n Returns\n -------\n base_fee_per_gas : `Uint`\n Base fee per gas for the block.\n ')), + Assign( + targets=[ + Name(id='parent_gas_target', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='ELASTICITY_MULTIPLIER', ctx=Load()))), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Name(id='block_gas_limit', ctx=Load()), + Name(id='parent_gas_limit', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='parent_gas_used', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='parent_gas_target', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=Name(id='parent_base_fee_per_gas', ctx=Load()))], + orelse=[ + If( + test=Compare( + left=Name(id='parent_gas_used', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='parent_gas_target', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='gas_used_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_used', ctx=Load()), + op=Sub(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='parent_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Mult(), + right=Name(id='gas_used_delta', ctx=Load()))), + Assign( + targets=[ + Name(id='target_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='base_fee_per_gas_delta', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=Name(id='target_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Load())), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Add(), + right=Name(id='base_fee_per_gas_delta', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='gas_used_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_target', ctx=Load()), + op=Sub(), + right=Name(id='parent_gas_used', ctx=Load()))), + Assign( + targets=[ + Name(id='parent_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Mult(), + right=Name(id='gas_used_delta', ctx=Load()))), + Assign( + targets=[ + Name(id='target_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='base_fee_per_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='target_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Load()))), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Sub(), + right=Name(id='base_fee_per_gas_delta', ctx=Load())))])]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='expected_base_fee_per_gas', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_base_fee_per_gas', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='expected_base_fee_per_gas', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='parent_has_ommers', ctx=Store())], + value=Compare( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='EMPTY_OMMER_HASH', ctx=Load())])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_difficulty', ctx=Store())], + value=Call( + func=Name(id='calculate_block_difficulty', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Name(id='parent_has_ommers', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_difficulty', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='validate_proof_of_work', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generate_header_hash_for_pow', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate rlp hash of the header which is to be used for Proof-of-Work\n verification.\n\n In other words, the PoW artefacts `mix_digest` and `nonce` are ignored\n while calculating this hash.\n\n A particular PoW is valid for a single hash, that hash is computed by\n this function. The `nonce` and `mix_digest` are omitted from this hash\n because they are being changed by miners in their search for a sufficient\n proof-of-work.\n\n Parameters\n ----------\n header :\n The header object for which the hash is to be generated.\n\n Returns\n -------\n hash : `Hash32`\n The PoW valid rlp hash of the passed in header.\n ')), + Assign( + targets=[ + Name(id='header_data_without_pow_artefacts', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='state_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='transactions_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='receipt_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='bloom', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='header_data_without_pow_artefacts', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='validate_proof_of_work', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the Proof of Work constraints.\n\n In order to verify that a miner's proof-of-work is valid for a block, a\n ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``\n hash function. The mix digest is a hash of the header and the nonce that\n is passed through and it confirms whether or not proof-of-work was done\n on the correct block. The result is the actual hash value of the block.\n\n Parameters\n ----------\n header :\n Header of interest.\n ")), + Assign( + targets=[ + Name(id='header_hash', ctx=Store())], + value=Call( + func=Name(id='generate_header_hash_for_pow', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache', ctx=Store())], + value=Call( + func=Name(id='generate_cache', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='mix_digest', ctx=Store()), + Name(id='result', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='hashimoto_light', ctx=Load()), + args=[ + Name(id='header_hash', ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + Name(id='cache', ctx=Load()), + Call( + func=Name(id='dataset_size', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='mix_digest', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='mix_digest', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='limit', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='limit', ctx=Load()), + op=FloorDiv(), + right=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n base_fee_per_gas :\n The block base fee.\n gas_available :\n The gas remaining in the block.\n chain_id :\n The ID of the current chain.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n effective_gas_price :\n The price to charge for gas when the transaction is executed.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='base_fee_per_gas', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='priority_fee_per_gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + op=Sub(), + right=Name(id='base_fee_per_gas', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='effective_gas_price', ctx=Store())], + value=BinOp( + left=Name(id='priority_fee_per_gas', ctx=Load()), + op=Add(), + right=Name(id='base_fee_per_gas', ctx=Load())))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='base_fee_per_gas', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='effective_gas_price', ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))]), + Return( + value=Tuple( + elts=[ + Name(id='sender_address', ctx=Load()), + Name(id='effective_gas_price', ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='error', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n error :\n Error in the top level frame of the transaction, if any.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='succeeded', + value=Compare( + left=Name(id='error', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)])), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='receipt', ctx=Load())], + keywords=[])))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='receipt', ctx=Load())], + keywords=[])))], + orelse=[ + Return( + value=Name(id='receipt', ctx=Load()))])])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Receipt', ctx=Load())], + ctx=Load()), + ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='block_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n base_fee_per_gas :\n Base fee per gas of within the block.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n block_difficulty :\n Difficulty of the block.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Receipt', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Call( + func=Name(id='map', ctx=Load()), + args=[ + Name(id='decode_transaction', ctx=Load()), + Name(id='transactions', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Call( + func=Name(id='encode_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='sender_address', ctx=Store()), + Name(id='effective_gas_price', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='base_fee_per_gas', ctx=Load()), + Name(id='gas_available', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='base_fee_per_gas', + value=Name(id='base_fee_per_gas', ctx=Load())), + keyword( + arg='gas_price', + value=Name(id='effective_gas_price', ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='difficulty', + value=Name(id='block_difficulty', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='chain_id', + value=Name(id='chain_id', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store()), + Name(id='error', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='error', ctx=Load()), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='pay_rewards', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='block_number', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='ommers', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='validate_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='block_header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the ommers mentioned in the block.\n\n An ommer block is a block that wasn't canonically added to the\n blockchain because it wasn't validated as fast as the canonical block\n but was mined at the same time.\n\n To be considered valid, the ommers must adhere to the rules defined in\n the Ethereum protocol. The maximum amount of ommers is 2 per block and\n there cannot be duplicate ommers in a block. Many of the other ommer\n constraints are listed in the in-line comments of this function.\n\n Parameters\n ----------\n ommers :\n List of ommers mentioned in the current block.\n block_header:\n The header of current block.\n chain :\n History and current state.\n ")), + Assign( + targets=[ + Name(id='block_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='block_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='ommers_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return()], + orelse=[]), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + op=Sub(), + right=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Name(id='ommer', ctx=Load()), + Name(id='ommer_parent_header', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=2)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommers_hashes', ctx=Store())], + value=ListComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + ifs=[], + is_async=0)])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[])], + keywords=[])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_canonical_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=BinOp( + left=Name(id='MAX_OMMER_DEPTH', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + ctx=Load())), + Assign( + targets=[ + Name(id='recent_canonical_block_hashes', ctx=Store())], + value=SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='recent_ommers_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + simple=1), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='recent_ommers_hashes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='recent_ommers_hashes', ctx=Load()), + attr='union', + ctx=Load()), + args=[ + SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='ommer_index', ctx=Store()), + Name(id='ommer', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='ommer_hash', ctx=Store())], + value=Subscript( + value=Name(id='ommers_hashes', ctx=Load()), + slice=Name(id='ommer_index', ctx=Load()), + ctx=Load())), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='block_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_ommers_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='ommer_age', ctx=Load())]), + Compare( + left=Name(id='ommer_age', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_OMMER_DEPTH', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='parent_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pay_rewards', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pay rewards to the block miner as well as the ommers miners.\n\n The miner of the canonical block is rewarded with the predetermined\n block reward, ``BLOCK_REWARD``, plus a variable award based off of the\n number of ommer blocks that were mined around the same time, and included\n in the canonical block's header. An ommer block is a block that wasn't\n added to the canonical blockchain because it wasn't validated as fast as\n the accepted block but was mined at the same time. Although not all blocks\n that are mined are added to the canonical chain, miners are still paid a\n reward for their efforts. This reward is called an ommer reward and is\n calculated based on the number associated with the ommer block that they\n mined.\n\n Parameters\n ----------\n state :\n Current account state.\n block_number :\n Position of the block within the chain.\n coinbase :\n Address of account which receives block reward and transaction fees.\n ommers :\n List of ommers mentioned in the current block.\n ")), + Assign( + targets=[ + Name(id='ommer_count', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='miner_reward', ctx=Store())], + value=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='ommer_count', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='miner_reward', ctx=Load())], + keywords=[])), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_number', ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='ommer_miner_reward', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Sub(), + right=Name(id='ommer_age', ctx=Load())), + op=Mult(), + right=Name(id='BLOCK_REWARD', ctx=Load())), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='ommer_miner_reward', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + AnnAssign( + target=Name(id='max_gas_fee', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='max_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load())], + keywords=[])))], + orelse=[ + Assign( + targets=[ + Name(id='max_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])))]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='max_gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='effective_gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='effective_gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='preaccessed_addresses', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='preaccessed_storage_keys', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Tuple( + elts=[ + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='address', ctx=Store()), + Name(id='keys', ctx=Store())], + ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='keys', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_storage_keys', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Name(id='address', ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[ + keyword( + arg='preaccessed_addresses', + value=Call( + func=Name(id='frozenset', ctx=Load()), + args=[ + Name(id='preaccessed_addresses', ctx=Load())], + keywords=[])), + keyword( + arg='preaccessed_storage_keys', + value=Call( + func=Name(id='frozenset', ctx=Load()), + args=[ + Name(id='preaccessed_storage_keys', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='priority_fee_per_gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Name(id='priority_fee_per_gas', ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + If( + test=Compare( + left=Name(id='coinbase_balance_after_mining_fee', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]))], + orelse=[])]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='error', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Name(id='TX_CREATE_COST', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Assign( + targets=[ + Name(id='access_list_cost', ctx=Store())], + value=Constant(value=0)), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Tuple( + elts=[ + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='_address', ctx=Store()), + Name(id='keys', ctx=Store())], + ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + body=[ + AugAssign( + target=Name(id='access_list_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_ACCESS_LIST_ADDRESS_COST', ctx=Load())), + AugAssign( + target=Name(id='access_list_cost', ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='keys', ctx=Load())], + keywords=[]), + op=Mult(), + right=Name(id='TX_ACCESS_LIST_STORAGE_KEY_COST', ctx=Load())))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load())), + op=Add(), + right=Name(id='access_list_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=28)])]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash_pre155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='chain_id_x2', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=36)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[])), + op=Sub(), + right=Name(id='chain_id_x2', ctx=Load())), + Call( + func=Name(id='signing_hash_155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])], + keywords=[]))])], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='y_parity', + ctx=Load()), + Call( + func=Name(id='signing_hash_2930', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='y_parity', + ctx=Load()), + Call( + func=Name(id='signing_hash_1559', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])])]), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash_pre155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='LegacyTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a legacy (pre EIP 155) signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='LegacyTransaction', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 155 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n The id of the current chain.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='chain_id', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_2930', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='AccessListTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 2930 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load())], + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_1559', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='FeeMarketTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 1559 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load())], + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_has_ommers', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes difficulty of a block using its header and parent header.\n\n The difficulty is determined by the time the block was created after its\n parent. The ``offset`` is calculated using the parent block's difficulty,\n ``parent_difficulty``, and the timestamp between blocks. This offset is\n then added to the parent difficulty and is stored as the ``difficulty``\n variable. If the time between the block and its parent is too short, the\n offset will result in a positive number thus making the sum of\n ``parent_difficulty`` and ``offset`` to be a greater value in order to\n avoid mass forking. But, if the time is long enough, then the offset\n results in a negative value making the block less difficult than\n its parent.\n\n The base standard for a block's difficulty is the predefined value\n set for the genesis block since it has no parent. So, a block\n can't be less difficult than the genesis block, therefore each block's\n difficulty is set to the maximum value between the calculated\n difficulty and the ``GENESIS_DIFFICULTY``.\n\n Parameters\n ----------\n block_number :\n Block number of the block.\n block_timestamp :\n Timestamp of the block.\n parent_timestamp :\n Timestamp of the parent block.\n parent_difficulty :\n difficulty of the parent block.\n parent_has_ommers:\n does the parent have ommers.\n\n Returns\n -------\n difficulty : `ethereum.base_types.Uint`\n Computed difficulty for a block.\n ")), + Assign( + targets=[ + Name(id='offset', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=2048)), + op=Mult(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=IfExp( + test=Name(id='parent_has_ommers', ctx=Load()), + body=Constant(value=2), + orelse=Constant(value=1)), + op=Sub(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_timestamp', ctx=Load()), + op=Sub(), + right=Name(id='parent_timestamp', ctx=Load()))], + keywords=[]), + op=FloorDiv(), + right=Constant(value=9))), + UnaryOp( + op=USub(), + operand=Constant(value=99))], + keywords=[]))), + Assign( + targets=[ + Name(id='difficulty', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='offset', ctx=Load()))), + Assign( + targets=[ + Name(id='num_bomb_periods', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='BOMB_DELAY_BLOCKS', ctx=Load())), + op=FloorDiv(), + right=Constant(value=100000)), + op=Sub(), + right=Constant(value=2))), + If( + test=Compare( + left=Name(id='num_bomb_periods', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='difficulty', ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Name(id='num_bomb_periods', ctx=Load())))], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='difficulty', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/fork.v b/coq/ethereum/gray_glacier/fork.v new file mode 100644 index 0000000000..37cba61d8e --- /dev/null +++ b/coq/ethereum/gray_glacier/fork.v @@ -0,0 +1,946 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.ethash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.gray_glacier.__init__. +Require ethereum.gray_glacier.blocks. +Require ethereum.gray_glacier.bloom. +Require ethereum.gray_glacier.fork_types. +Require ethereum.gray_glacier.state. +Require ethereum.gray_glacier.transactions. +Require ethereum.gray_glacier.trie. +Require ethereum.gray_glacier.utils.message. +Require ethereum.gray_glacier.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + do* [[ M.get_local ~(| "validate_ommers" |) ~(| + M.get_field ~(| block, "ommers" |), + M.get_field ~(| block, "header" |), + chain + |) ]] in + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "base_fee_per_gas" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "difficulty" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| block, "ommers" |), + M.get_field ~(| chain, "chain_id" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_base_fee_per_gas (block_gas_limit : Uint) (parent_gas_limit : Uint) (parent_gas_used : Uint) (parent_base_fee_per_gas : Uint) : M Uint := + (* + 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. + *) + do* M.assign "parent_gas_target" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + (* TODO statement *) + do* M.assign "expected_base_fee_per_gas" [[ + M.get_local ~(| "calculate_base_fee_per_gas" |) ~(| + M.get_field ~(| header, "gas_limit" |), + M.get_field ~(| parent_header, "gas_limit" |), + M.get_field ~(| parent_header, "gas_used" |), + M.get_field ~(| parent_header, "base_fee_per_gas" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "parent_has_ommers" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_difficulty" [[ + M.get_local ~(| "calculate_block_difficulty" |) ~(| + M.get_field ~(| header, "number" |), + M.get_field ~(| header, "timestamp" |), + M.get_field ~(| parent_header, "timestamp" |), + M.get_field ~(| parent_header, "difficulty" |), + M.get_local ~(| "parent_has_ommers" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| + header + |) ]] in + M.pure tt. + +Definition generate_header_hash_for_pow (header : Header) : M Hash32 := + (* + 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. + *) + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_proof_of_work (header : Header) : M unit := + (* + 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. + *) + do* M.assign "header_hash" [[ + M.get_local ~(| "generate_header_hash_for_pow" |) ~(| + header + |) in + ]] in + do* M.assign "cache" [[ + ethereum.ethash.generate_cache ~(| + M.get_field ~(| header, "number" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (base_fee_per_gas : Uint) (gas_available : Uint) (chain_id : U64) : M (* TODO type *) := + (* + 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. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (error : (* TODO type *)) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (base_fee_per_gas : Uint) (block_gas_limit : Uint) (block_time : U256) (block_difficulty : Uint) (transactions : (* TODO type *)) (ommers : (* TODO type *)) (chain_id : U64) : M ApplyBodyOutput := + (* + 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 + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "pay_rewards" |) ~(| + state, + block_number, + coinbase, + ommers + |) ]] in + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_ommers (ommers : (* TODO type *)) (block_header : Header) (chain : BlockChain) : M unit := + (* + 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. + *) + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_canonical_blocks" [[ + (* TODO expression *) in + ]] in + do* M.assign "recent_canonical_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition pay_rewards (state : State) (block_number : Uint) (coinbase : Address) (ommers : (* TODO type *)) : M unit := + (* + 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. + *) + do* M.assign "ommer_count" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + ommers + |) + |) in + ]] in + do* M.assign "miner_reward" [[ + (* TODO expression *) in + ]] in + do* [[ state.create_ether ~(| + state, + coinbase, + M.get_local ~(| "miner_reward" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "effective_gas_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "preaccessed_addresses" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "preaccessed_storage_keys" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + (* TODO statement *) + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "priority_fee_per_gas" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "access_list_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_pre155 (tx : LegacyTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_155 (tx : LegacyTransaction) (chain_id : U64) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_2930 (tx : AccessListTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_1559 (tx : FeeMarketTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_block_difficulty (block_number : Uint) (block_timestamp : U256) (parent_timestamp : U256) (parent_difficulty : Uint) (parent_has_ommers : bool) : M Uint := + (* + 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. + *) + do* M.assign "offset" [[ + (* TODO expression *) in + ]] in + do* M.assign "difficulty" [[ + (* TODO expression *) in + ]] in + do* M.assign "num_bomb_periods" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/fork_types.ast b/coq/ethereum/gray_glacier/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/gray_glacier/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/fork_types.v b/coq/ethereum/gray_glacier/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/gray_glacier/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/state.ast b/coq/ethereum/gray_glacier/state.ast new file mode 100644 index 0000000000..c04909fdce --- /dev/null +++ b/coq/ethereum/gray_glacier/state.ast @@ -0,0 +1,1692 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='created_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='set', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mark_account_created', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Mark an account as having been created in the current transaction.\n This information is used by `get_storage_original()` to handle an obscure\n edgecase.\n\n The marker is not removed even if the account creation reverts. Since the\n account cannot have had code prior to its creation and can't call\n `get_storage_original()`, this is harmless.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account that has been created.\n ")), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has zero nonce, empty code and zero balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_empty : `bool`\n True if if an account has zero nonce, empty code and zero balance,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_exists_and_is_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists and has zero nonce, empty code and zero\n balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n exists_and_is_empty : `bool`\n True if an account exists and has zero nonce, empty code and zero\n balance, False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='account', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_alive', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether is an account is both in the state and non empty.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_alive : `bool`\n True if the account is alive.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[ + Return( + value=UnaryOp( + op=Not(), + operand=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])])))])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add newly created ether to an account.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to which ether is added.\n amount:\n The amount of ether to be added to the account of interest.\n ')), + FunctionDef( + name='increase_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage_original', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the original value in a storage slot i.e. the value before the current\n transaction began. This function reads the value from the snapshots taken\n before executing the transaction.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to read the value from.\n key:\n Key of the storage slot.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='_', ctx=Store()), + Name(id='original_trie', ctx=Store())], + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + Assign( + targets=[ + Name(id='original_account_trie', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='original_trie', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='original_account_trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='original_account_trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[]))]), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='original_value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='original_value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/state.v b/coq/ethereum/gray_glacier/state.v new file mode 100644 index 0000000000..854221db7c --- /dev/null +++ b/coq/ethereum/gray_glacier/state.v @@ -0,0 +1,614 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.gray_glacier.fork_types. +Require ethereum.gray_glacier.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition mark_account_created (state : State) (address : Address) : M unit := + (* + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| + address + |) ]] in + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_empty (state : State) (address : Address) : M bool := + (* + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition account_exists_and_is_empty (state : State) (address : Address) : M bool := + (* + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_alive (state : State) (address : Address) : M bool := + (* + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := + (* + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. + +Definition get_storage_original (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + *) + (* TODO statement *) + (* TODO assignment *) + do* M.assign "original_account_trie" [[ + M.get_field ~(| M.get_local ~(| "original_trie" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/transactions.ast b/coq/ethereum/gray_glacier/transactions.ast new file mode 100644 index 0000000000..264b048f3f --- /dev/null +++ b/coq/ethereum/gray_glacier/transactions.ast @@ -0,0 +1,492 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='TransactionTypeError')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + Assign( + targets=[ + Name(id='TX_ACCESS_LIST_ADDRESS_COST', ctx=Store())], + value=Constant(value=2400)), + Assign( + targets=[ + Name(id='TX_ACCESS_LIST_STORAGE_KEY_COST', ctx=Store())], + value=Constant(value=1900)), + ClassDef( + name='LegacyTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='AccessListTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The transaction type added in EIP-2930 to support access lists.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='access_list', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y_parity', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='FeeMarketTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The transaction type added in EIP-1559.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_priority_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='access_list', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y_parity', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='Transaction', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Encode a transaction. Needed because non-legacy transactions aren't RLP.\n ")), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='tx', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])))], + orelse=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Unable to encode transaction of type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + conversion=-1)])], + keywords=[]))])])])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='decode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Decode a transaction. Needed because non-legacy transactions aren't RLP.\n ")), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Name(id='AccessListTransaction', ctx=Load()), + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=2)]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Name(id='FeeMarketTransaction', ctx=Load()), + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())], + keywords=[]))], + orelse=[ + Raise( + exc=Call( + func=Name(id='TransactionTypeError', ctx=Load()), + args=[ + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]))])])], + orelse=[ + Return( + value=Name(id='tx', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Transaction', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/transactions.v b/coq/ethereum/gray_glacier/transactions.v new file mode 100644 index 0000000000..3223df95d8 --- /dev/null +++ b/coq/ethereum/gray_glacier/transactions.v @@ -0,0 +1,29 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.gray_glacier.exceptions. +Require ethereum.gray_glacier.fork_types. + +Definition encode_transaction (tx : Transaction) : M (* TODO type *) := + (* + Encode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + M.pure tt. + +Definition decode_transaction (tx : (* TODO type *)) : M Transaction := + (* + Decode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/trie.ast b/coq/ethereum/gray_glacier/trie.ast new file mode 100644 index 0000000000..211a5440d6 --- /dev/null +++ b/coq/ethereum/gray_glacier/trie.ast @@ -0,0 +1,1632 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.arrow_glacier', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='LegacyTransaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Receipt', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.RLP`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/trie.v b/coq/ethereum/gray_glacier/trie.v new file mode 100644 index 0000000000..6b8953f256 --- /dev/null +++ b/coq/ethereum/gray_glacier/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/utils/__init__.ast b/coq/ethereum/gray_glacier/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/gray_glacier/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/utils/__init__.v b/coq/ethereum/gray_glacier/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/gray_glacier/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/gray_glacier/utils/address.ast b/coq/ethereum/gray_glacier/utils/address.ast new file mode 100644 index 0000000000..629ebfd57f --- /dev/null +++ b/coq/ethereum/gray_glacier/utils/address.ast @@ -0,0 +1,216 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this gray_glacier version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_create2_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='salt', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='call_data', + annotation=Name(id='bytearray', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created, which is\n based on the sender address, salt and the call data as well.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n salt :\n Address generation salt.\n call_data :\n The code of the new account which is to be created.\n\n Returns\n -------\n address: `ethereum.gray_glacier.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='preimage', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Constant(value=b'\xff'), + op=Add(), + right=Name(id='address', ctx=Load())), + op=Add(), + right=Name(id='salt', ctx=Load())), + op=Add(), + right=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='call_data', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/utils/address.v b/coq/ethereum/gray_glacier/utils/address.v new file mode 100644 index 0000000000..fbc8732917 --- /dev/null +++ b/coq/ethereum/gray_glacier/utils/address.v @@ -0,0 +1,115 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this gray_glacier version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.gray_glacier.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition compute_create2_contract_address (address : Address) (salt : Bytes32) (call_data : bytearray) : M Address := + (* + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.gray_glacier.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "preimage" [[ + (* TODO expression *) in + ]] in + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "preimage" |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/utils/hexadecimal.ast b/coq/ethereum/gray_glacier/utils/hexadecimal.ast new file mode 100644 index 0000000000..61ed03e9b1 --- /dev/null +++ b/coq/ethereum/gray_glacier/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to\nGray Glacier types.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/utils/hexadecimal.v b/coq/ethereum/gray_glacier/utils/hexadecimal.v new file mode 100644 index 0000000000..8de558f56b --- /dev/null +++ b/coq/ethereum/gray_glacier/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Gray Glacier types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.gray_glacier.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/utils/message.ast b/coq/ethereum/gray_glacier/utils/message.ast new file mode 100644 index 0000000000..1ecd0704b8 --- /dev/null +++ b/coq/ethereum/gray_glacier/utils/message.ast @@ -0,0 +1,335 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this gray_glacier version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='FrozenSet'), + alias(name='Optional'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_static', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='preaccessed_addresses', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='preaccessed_storage_keys', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True), + Constant(value=False), + Call( + func=Name(id='frozenset', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='frozenset', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n is_static:\n if True then it prevents all state-changing operations from being\n executed.\n preaccessed_addresses:\n Addresses that should be marked as accessed prior to the message call\n preaccessed_storage_keys:\n Storage keys that should be marked as accessed prior to the message\n call\n\n Returns\n -------\n message: `ethereum.gray_glacier.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Assign( + targets=[ + Name(id='accessed_addresses', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='current_target', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='caller', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Name(id='preaccessed_addresses', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=Name(id='is_static', ctx=Load())), + keyword( + arg='accessed_addresses', + value=Name(id='accessed_addresses', ctx=Load())), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='preaccessed_storage_keys', ctx=Load())], + keywords=[])), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/utils/message.v b/coq/ethereum/gray_glacier/utils/message.v new file mode 100644 index 0000000000..0f4d824221 --- /dev/null +++ b/coq/ethereum/gray_glacier/utils/message.v @@ -0,0 +1,85 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this gray_glacier version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.gray_glacier.fork_types. +Require ethereum.gray_glacier.state. +Require ethereum.gray_glacier.vm. +Require ethereum.gray_glacier.vm.precompiled_contracts.mapping. +Require ethereum.gray_glacier.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) (is_static : bool) (preaccessed_addresses : (* TODO type *)) (preaccessed_storage_keys : (* TODO type *)) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.gray_glacier.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + do* M.assign "accessed_addresses" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "add" |) ~(| + M.get_local ~(| "current_target" |) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "add" |) ~(| + caller + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS, "keys" |) ~(| + + |) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + preaccessed_addresses + |) ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/__init__.ast b/coq/ethereum/gray_glacier/vm/__init__.ast new file mode 100644 index 0000000000..5290882162 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/__init__.ast @@ -0,0 +1,591 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty')], + level=2), + ImportFrom( + module='precompiled_contracts', + names=[ + alias(name='RIPEMD160_ADDRESS')], + level=1), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='is_static', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_addresses', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_storage_keys', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='return_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_addresses', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_storage_keys', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + If( + test=Compare( + left=Name(id='RIPEMD160_ADDRESS', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/__init__.v b/coq/ethereum/gray_glacier/vm/__init__.v new file mode 100644 index 0000000000..0c6b028c65 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/__init__.v @@ -0,0 +1,78 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.gray_glacier.blocks. +Require ethereum.gray_glacier.fork_types. +Require ethereum.gray_glacier.state. +Require ethereum.gray_glacier.vm.precompiled_contracts. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "touched_accounts" |), "update" |) ~(| + M.get_field ~(| child_evm, "touched_accounts" |) + |) ]] in + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| child_evm, "accessed_addresses" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_storage_keys" |), "update" |) ~(| + M.get_field ~(| child_evm, "accessed_storage_keys" |) + |) ]] in + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + (* TODO statement *) + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/exceptions.ast b/coq/ethereum/gray_glacier/vm/exceptions.ast new file mode 100644 index 0000000000..79ecb4b47d --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/exceptions.ast @@ -0,0 +1,175 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='Revert', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised by the `REVERT` opcode.\n\n Unlike other EVM exceptions this does not result in the consumption of all\n gas.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='WriteInStaticContext', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt is made to modify the state while operating inside\n of a STATICCALL context.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfBoundsRead', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt was made to read data beyond the\n boundaries of the buffer.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidParameter', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when invalid parameters are passed.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidContractPrefix', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract code starts with 0xEF.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/exceptions.v b/coq/ethereum/gray_glacier/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/gray_glacier/vm/gas.ast b/coq/ethereum/gray_glacier/vm/gas.ast new file mode 100644 index 0000000000..33b4cae82f --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/gas.ast @@ -0,0 +1,813 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=4800)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RETURN_DATA_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_FAST_STEP', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLAKE2_PER_ROUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COLD_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2100)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_WARM_ACCESS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=100)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_left', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='memory_cost', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='extra_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='call_stipend', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Expr( + value=Constant(value='\n Calculates the MessageCallGas (cost and stipend) for\n executing call Opcodes.\n\n Parameters\n ----------\n value:\n The amount of `ETH` that needs to be transferred.\n gas :\n The amount of gas provided to the message-call.\n gas_left :\n The amount of gas left in the current frame.\n memory_cost :\n The amount needed to extend the memory in the current frame.\n extra_gas :\n The amount of gas needed for transferring value + creating a new\n account inside a message call.\n call_stipend :\n The amount of stipend provided to a message call to execute code while\n transferring value(ETH).\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='call_stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='call_stipend', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='extra_gas', ctx=Load()), + op=Add(), + right=Name(id='memory_cost', ctx=Load()))]), + body=[ + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='gas', ctx=Load()), + Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='gas_left', ctx=Load()), + op=Sub(), + right=Name(id='memory_cost', ctx=Load())), + op=Sub(), + right=Name(id='extra_gas', ctx=Load()))], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load())), + FunctionDef( + name='max_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the maximum gas that is allowed for making a message call\n\n Parameters\n ----------\n gas :\n The amount of gas provided to the message-call.\n\n Returns\n -------\n max_allowed_message_call_gas: `ethereum.base_types.Uint`\n The maximum gas allowed for making the message-call.\n ')), + Return( + value=BinOp( + left=Name(id='gas', ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='gas', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]))))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/gas.v b/coq/ethereum/gray_glacier/vm/gas.v new file mode 100644 index 0000000000..ca889413c1 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/gas.v @@ -0,0 +1,171 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (value : U256) (gas : Uint) (gas_left : Uint) (memory_cost : Uint) (extra_gas : Uint) (call_stipend : Uint) : M MessageCallGas := + (* + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "gas" [[ + M.get_local ~(| "min" |) ~(| + gas, + M.get_local ~(| "max_message_call_gas" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition max_message_call_gas (gas : Uint) : M Uint := + (* + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/instructions/__init__.ast b/coq/ethereum/gray_glacier/vm/instructions/__init__.ast new file mode 100644 index 0000000000..5dae83fbf2 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/__init__.ast @@ -0,0 +1,1792 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='SHL', ctx=Store())], + value=Constant(value=27)), + Assign( + targets=[ + Name(id='SHR', ctx=Store())], + value=Constant(value=28)), + Assign( + targets=[ + Name(id='SAR', ctx=Store())], + value=Constant(value=29)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='RETURNDATASIZE', ctx=Store())], + value=Constant(value=61)), + Assign( + targets=[ + Name(id='RETURNDATACOPY', ctx=Store())], + value=Constant(value=62)), + Assign( + targets=[ + Name(id='EXTCODEHASH', ctx=Store())], + value=Constant(value=63)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='DIFFICULTY', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='CHAINID', ctx=Store())], + value=Constant(value=70)), + Assign( + targets=[ + Name(id='SELFBALANCE', ctx=Store())], + value=Constant(value=71)), + Assign( + targets=[ + Name(id='BASEFEE', ctx=Store())], + value=Constant(value=72)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='CREATE2', ctx=Store())], + value=Constant(value=245)), + Assign( + targets=[ + Name(id='STATICCALL', ctx=Store())], + value=Constant(value=250)), + Assign( + targets=[ + Name(id='REVERT', ctx=Store())], + value=Constant(value=253)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SAR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIFFICULTY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CHAINID', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODEHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFBALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BASEFEE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STATICCALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='REVERT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE2', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shl', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shr', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_sar', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodehash', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='self_balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='base_fee', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='staticcall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='revert', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create2', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/instructions/__init__.v b/coq/ethereum/gray_glacier/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/gray_glacier/vm/instructions/arithmetic.ast b/coq/ethereum/gray_glacier/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/instructions/arithmetic.v b/coq/ethereum/gray_glacier/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..18132d79ee --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/instructions/bitwise.ast b/coq/ethereum/gray_glacier/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..b72397f0ec --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/bitwise.ast @@ -0,0 +1,751 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shl', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift left (SHL) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='value', ctx=Load()), + op=LShift(), + right=Name(id='shift', ctx=Load())), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]))], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shr', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift right (SHR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_sar', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Arithmetic shift right (SAR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='signed_value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=256)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + BinOp( + left=Name(id='signed_value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load()))], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='signed_value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load()))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/instructions/bitwise.v b/coq/ethereum/gray_glacier/vm/instructions/bitwise.v new file mode 100644 index 0000000000..2341fa42db --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/bitwise.v @@ -0,0 +1,309 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shl (evm : Evm) : M unit := + (* + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shr (evm : Evm) : M unit := + (* + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_sar (evm : Evm) : M unit := + (* + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + M.get_local ~(| "int" |) ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "signed_value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/instructions/block.ast b/coq/ethereum/gray_glacier/vm/instructions/block.ast new file mode 100644 index 0000000000..b9ccb3290b --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/block.ast @@ -0,0 +1,492 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's difficulty onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='chain_id', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the chain id onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/instructions/block.v b/coq/ethereum/gray_glacier/vm/instructions/block.v new file mode 100644 index 0000000000..1c04eac1b9 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/block.v @@ -0,0 +1,241 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition difficulty (evm : Evm) : M unit := + (* + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition chain_id (evm : Evm) : M unit := + (* + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/instructions/comparison.ast b/coq/ethereum/gray_glacier/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/instructions/comparison.v b/coq/ethereum/gray_glacier/vm/instructions/comparison.v new file mode 100644 index 0000000000..498f90654e --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/instructions/control_flow.ast b/coq/ethereum/gray_glacier/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/instructions/control_flow.v b/coq/ethereum/gray_glacier/vm/instructions/control_flow.v new file mode 100644 index 0000000000..097ba5b4c8 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.exceptions. +Require ethereum.gray_glacier.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/instructions/environment.ast b/coq/ethereum/gray_glacier/vm/instructions/environment.ast new file mode 100644 index 0000000000..60bbfdaff1 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/environment.ast @@ -0,0 +1,1828 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfBoundsRead')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_COLD_ACCOUNT_ACCESS'), + alias(name='GAS_COPY'), + alias(name='GAS_FAST_STEP'), + alias(name='GAS_RETURN_DATA_COPY'), + alias(name='GAS_VERY_LOW'), + alias(name='GAS_WARM_ACCESS'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_WARM_ACCESS', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the size of the return data buffer onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copies data from the return data buffer code to memory\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='return_data_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_RETURN_DATA_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='return_data_start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfBoundsRead', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load()), + slice=Slice( + lower=Name(id='return_data_start_position', ctx=Load()), + upper=BinOp( + left=Name(id='return_data_start_position', ctx=Load()), + op=Add(), + right=Name(id='size', ctx=Load()))), + ctx=Load())), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodehash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns the keccak256 hash of a contract’s bytecode\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='EMPTY_ACCOUNT', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codehash', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='self_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the current address to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_FAST_STEP', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='base_fee', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the base fee of the current block on to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/instructions/environment.v b/coq/ethereum/gray_glacier/vm/instructions/environment.v new file mode 100644 index 0000000000..73f9c217bf --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/environment.v @@ -0,0 +1,728 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.gray_glacier.fork_types. +Require ethereum.gray_glacier.state. +Require ethereum.gray_glacier.utils.address. +Require ethereum.gray_glacier.vm.memory. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.exceptions. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatasize (evm : Evm) : M unit := + (* + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatacopy (evm : Evm) : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "return_data_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + (* TODO expression *) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodehash (evm : Evm) : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "account" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codehash" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition self_balance (evm : Evm) : M unit := + (* + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_FAST_STEP + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition base_fee (evm : Evm) : M unit := + (* + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "base_fee_per_gas" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/instructions/keccak.ast b/coq/ethereum/gray_glacier/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/instructions/keccak.v b/coq/ethereum/gray_glacier/vm/instructions/keccak.v new file mode 100644 index 0000000000..6efe8c5fd9 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.memory. +Require ethereum.gray_glacier.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/instructions/log.ast b/coq/ethereum/gray_glacier/vm/instructions/log.ast new file mode 100644 index 0000000000..0ded0e04ba --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/log.ast @@ -0,0 +1,323 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/instructions/log.v b/coq/ethereum/gray_glacier/vm/instructions/log.v new file mode 100644 index 0000000000..2ed6fac93f --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/log.v @@ -0,0 +1,79 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.gray_glacier.blocks. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.exceptions. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.memory. +Require ethereum.gray_glacier.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO statement *) + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/instructions/memory.ast b/coq/ethereum/gray_glacier/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/instructions/memory.v b/coq/ethereum/gray_glacier/vm/instructions/memory.v new file mode 100644 index 0000000000..d9fac1b733 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.memory. +Require ethereum.gray_glacier.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/instructions/stack.ast b/coq/ethereum/gray_glacier/vm/instructions/stack.ast new file mode 100644 index 0000000000..95cfc0b6cf --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/stack.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/instructions/stack.v b/coq/ethereum/gray_glacier/vm/instructions/stack.v new file mode 100644 index 0000000000..309349a16f --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/stack.v @@ -0,0 +1,153 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.exceptions. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/instructions/storage.ast b/coq/ethereum/gray_glacier/vm/instructions/storage.ast new file mode 100644 index 0000000000..68640a90a8 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/storage.ast @@ -0,0 +1,551 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='get_storage_original'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_STIPEND'), + alias(name='GAS_COLD_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='GAS_WARM_ACCESS'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_SLOAD', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='get_storage_original', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + If( + test=Compare( + left=Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_COLD_SLOAD', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='current_value', ctx=Load())]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())])]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_COLD_SLOAD', ctx=Load())))])], + orelse=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))]), + If( + test=Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='GAS_STORAGE_SET', ctx=Load()), + op=Sub(), + right=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + keywords=[]))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_COLD_SLOAD', ctx=Load())), + op=Sub(), + right=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + keywords=[]))])], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/instructions/storage.v b/coq/ethereum/gray_glacier/vm/instructions/storage.v new file mode 100644 index 0000000000..ecf70597e2 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/storage.v @@ -0,0 +1,121 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.gray_glacier.state. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.exceptions. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "original_value" [[ + state.get_storage_original ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "gas_cost" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/instructions/system.ast b/coq/ethereum/gray_glacier/vm/instructions/system.ast new file mode 100644 index 0000000000..0fcb1135df --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/system.ast @@ -0,0 +1,2897 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='is_account_alive'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='compute_create2_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='Revert'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_VALUE'), + alias(name='GAS_COLD_ACCOUNT_ACCESS'), + alias(name='GAS_CREATE'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='GAS_NEW_ACCOUNT'), + alias(name='GAS_SELF_DESTRUCT'), + alias(name='GAS_SELF_DESTRUCT_NEW_ACCOUNT'), + alias(name='GAS_WARM_ACCESS'), + alias(name='GAS_ZERO'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas'), + alias(name='max_message_call_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='generic_create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='endowment', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='contract_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='memory_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Core logic used by the `CREATE*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='contract_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='create_message_gas', ctx=Load())), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='is_static', + value=Constant(value=False)), + keyword( + arg='accessed_addresses', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create2', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Creates a new account with associated code.\n\n It's similar to CREATE opcode except that the address of new account\n depends on the init_code instead of the nonce of sender.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ")), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='salt', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='call_data_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='call_data_words', ctx=Load()))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_create2_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='salt', ctx=Load()), + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_staticcall', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=IfExp( + test=Name(id='is_staticcall', ctx=Load()), + body=Constant(value=True), + orelse=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()))), + keyword( + arg='accessed_addresses', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='to', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=BoolOp( + op=Or(), + values=[ + Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[]), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='access_gas_cost', ctx=Load()), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='code_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=Name(id='access_gas_cost', ctx=Load()), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SELF_DESTRUCT', ctx=Load())), + If( + test=Compare( + left=Name(id='beneficiary', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[])), + Compare( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='code_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='access_gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='staticcall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='to', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='access_gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='revert', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop execution and revert state changes, without consuming all provided gas\n and also has the ability to return a reason\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Name(id='output', ctx=Load())], + keywords=[])), + Raise( + exc=Name(id='Revert', ctx=Load())), + Pass()], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/instructions/system.v b/coq/ethereum/gray_glacier/vm/instructions/system.v new file mode 100644 index 0000000000..948bccc517 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/instructions/system.v @@ -0,0 +1,779 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.gray_glacier.fork_types. +Require ethereum.gray_glacier.state. +Require ethereum.gray_glacier.utils.address. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.exceptions. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.memory. +Require ethereum.gray_glacier.vm.stack. + +Definition generic_create (evm : Evm) (endowment : U256) (contract_address : Address) (memory_start_position : U256) (memory_size : U256) : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "add" |) ~(| + contract_address + |) ]] in + do* M.assign "create_message_gas" [[ + gas.max_message_call_gas ~(| + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) in + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_local ~(| "create_message_gas" |) + ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_start_position, + memory_size + |) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_create_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition create2 (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "salt" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "call_data_words" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_create2_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "salt" |), + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (is_staticcall : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_SELF_DESTRUCT in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + M.get_local ~(| "access_gas_cost" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition staticcall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + M.get_local ~(| "access_gas_cost" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "to" |), + M.get_local ~(| "to" |), + True, + True, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition revert (evm : Evm) : M unit := + (* + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "output" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/interpreter.ast b/coq/ethereum/gray_glacier/vm/interpreter.ast new file mode 100644 index 0000000000..6411a26545 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/interpreter.ast @@ -0,0 +1,1177 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Iterable'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='increment_nonce'), + alias(name='mark_account_created'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidContractPrefix'), + alias(name='InvalidOpcode'), + alias(name='OutOfGasError'), + alias(name='Revert'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_CODE_SIZE', ctx=Store())], + value=Constant(value=24576)), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `touched_accounts`: Accounts that have been touched.\n 6. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='touched_accounts', + value=Name(id='touched_accounts', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.london.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='mark_account_created', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='contract_code', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=239)]), + body=[ + Raise( + exc=Name(id='InvalidContractPrefix', ctx=Load()))], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_CODE_SIZE', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.london.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='touched_accounts', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='return_data', + value=Constant(value=b'')), + keyword( + arg='error', + value=Constant(value=None)), + keyword( + arg='accessed_addresses', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='accessed_addresses', + ctx=Load())), + keyword( + arg='accessed_storage_keys', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))]), + ExceptHandler( + type=Name(id='Revert', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/interpreter.v b/coq/ethereum/gray_glacier/vm/interpreter.v new file mode 100644 index 0000000000..b4122d90ba --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/interpreter.v @@ -0,0 +1,173 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.gray_glacier.blocks. +Require ethereum.gray_glacier.fork_types. +Require ethereum.gray_glacier.state. +Require ethereum.gray_glacier.vm. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.precompiled_contracts.mapping. +Require ethereum.gray_glacier.vm.__init__. +Require ethereum.gray_glacier.vm.exceptions. +Require ethereum.gray_glacier.vm.instructions. +Require ethereum.gray_glacier.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.mark_account_created ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/memory.ast b/coq/ethereum/gray_glacier/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/memory.v b/coq/ethereum/gray_glacier/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/__init__.ast b/coq/ethereum/gray_glacier/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..bb9991907f --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS'), + Constant(value='MODEXP_ADDRESS'), + Constant(value='ALT_BN128_ADD_ADDRESS'), + Constant(value='ALT_BN128_MUL_ADDRESS'), + Constant(value='ALT_BN128_PAIRING_CHECK_ADDRESS'), + Constant(value='BLAKE2F_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[])), + Assign( + targets=[ + Name(id='MODEXP_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x05')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x06')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x07')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x08')], + keywords=[])), + Assign( + targets=[ + Name(id='BLAKE2F_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x09')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/__init__.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..ab3f148773 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.gray_glacier.utils.hexadecimal. diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.ast b/coq/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.ast new file mode 100644 index 0000000000..f6f077419c --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.ast @@ -0,0 +1,913 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ALT_BN128 CONTRACTS\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ALT_BN128 precompiled contracts.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.alt_bn128', + names=[ + alias(name='ALT_BN128_CURVE_ORDER'), + alias(name='ALT_BN128_PRIME'), + alias(name='BNF'), + alias(name='BNF2'), + alias(name='BNF12'), + alias(name='BNP'), + alias(name='BNP2'), + alias(name='pairing')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=2), + FunctionDef( + name='alt_bn128_add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 addition precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=150)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load()), + Name(id='x1_value', ctx=Load()), + Name(id='y1_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='p1', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x1_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y1_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=BinOp( + left=Name(id='p0', ctx=Load()), + op=Add(), + right=Name(id='p1', ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 multiplication precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6000)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='n', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='p0', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='n', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_pairing_check', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 pairing check precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=34000), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))), + op=Add(), + right=Constant(value=45000))], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=192)), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='values', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=Name(id='j', ctx=Load()))), + upper=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=BinOp( + left=Name(id='j', ctx=Load()), + op=Add(), + right=Constant(value=1))))), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='values', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=Call( + func=Name(id='BNP2', ctx=Load()), + args=[ + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=3), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=2), + ctx=Load())], + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=5), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=4), + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='OutOfGasError', ctx=Load()), + args=[], + keywords=[]))])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='p', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='q', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='p', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + Compare( + left=Name(id='q', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='result', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='pairing', ctx=Load()), + args=[ + Name(id='q', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[])))], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='result', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000000..e49a78fed5 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,226 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.alt_bn128. +Require ethereum.gray_glacier.vm. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.memory. +Require ethereum.gray_glacier.vm.exceptions. + +Definition alt_bn128_add (evm : Evm) : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 150 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "x1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x1_bytes" |) + |) + |) in + ]] in + do* M.assign "y1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y1_bytes" |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + (* TODO expression *) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_mul (evm : Evm) : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 6000 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "n" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + M.get_field ~(| M.get_local ~(| "p0" |), "mul_by" |) ~(| + M.get_local ~(| "n" |) + |) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_pairing_check (evm : Evm) : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + (* TODO expression *) + |) + |) ]] in + (* TODO statement *) + do* M.assign "result" [[ + M.get_field ~(| ethereum.crypto.alt_bn128.BNF12, "from_int" |) ~(| + 1 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.ast b/coq/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.ast new file mode 100644 index 0000000000..03747962f0 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.ast @@ -0,0 +1,137 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `Blake2` precompiled contract.\n')), + ImportFrom( + module='ethereum.crypto.blake2', + names=[ + alias(name='Blake2b')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BLAKE2_PER_ROUND'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidParameter')], + level=2), + FunctionDef( + name='blake2f', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the Blake2 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Constant(value=213)]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='blake2b', ctx=Store())], + value=Call( + func=Name(id='Blake2b', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='rounds', ctx=Store()), + Name(id='h', ctx=Store()), + Name(id='m', ctx=Store()), + Name(id='t_0', ctx=Store()), + Name(id='t_1', ctx=Store()), + Name(id='f', ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='get_blake2_parameters', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_BLAKE2_PER_ROUND', ctx=Load()), + op=Mult(), + right=Name(id='rounds', ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=Name(id='f', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + List( + elts=[ + Constant(value=0), + Constant(value=1)], + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='compress', + ctx=Load()), + args=[ + Name(id='rounds', ctx=Load()), + Name(id='h', ctx=Load()), + Name(id='m', ctx=Load()), + Name(id='t_0', ctx=Load()), + Name(id='t_1', ctx=Load()), + Name(id='f', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000000..61824c970a --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,46 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +*) + +Require ethereum.crypto.blake2. +Require ethereum.gray_glacier.vm. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.exceptions. + +Definition blake2f (evm : Evm) : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + (* TODO statement *) + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| + + |) in + ]] in + (* TODO assignment *) + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..f22e39c0ac --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.gray_glacier.vm. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/identity.ast b/coq/ethereum/gray_glacier/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/identity.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..71abf77228 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.gray_glacier.vm. +Require ethereum.gray_glacier.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/mapping.ast b/coq/ethereum/gray_glacier/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..cec40e5736 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ALT_BN128_ADD_ADDRESS'), + alias(name='ALT_BN128_MUL_ADDRESS'), + alias(name='ALT_BN128_PAIRING_CHECK_ADDRESS'), + alias(name='BLAKE2F_ADDRESS'), + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='MODEXP_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='alt_bn128', + names=[ + alias(name='alt_bn128_add'), + alias(name='alt_bn128_mul'), + alias(name='alt_bn128_pairing_check')], + level=1), + ImportFrom( + module='blake2f', + names=[ + alias(name='blake2f')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='modexp', + names=[ + alias(name='modexp')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load()), + Name(id='MODEXP_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Load()), + Name(id='BLAKE2F_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load()), + Name(id='modexp', ctx=Load()), + Name(id='alt_bn128_add', ctx=Load()), + Name(id='alt_bn128_mul', ctx=Load()), + Name(id='alt_bn128_pairing_check', ctx=Load()), + Name(id='blake2f', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/mapping.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..fd67a86d12 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/mapping.v @@ -0,0 +1,25 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.gray_glacier.fork_types. +Require ethereum.gray_glacier.vm.precompiled_contracts.__init__. +Require ethereum.gray_glacier.vm.precompiled_contracts.alt_bn128. +Require ethereum.gray_glacier.vm.precompiled_contracts.blake2f. +Require ethereum.gray_glacier.vm.precompiled_contracts.ecrecover. +Require ethereum.gray_glacier.vm.precompiled_contracts.identity. +Require ethereum.gray_glacier.vm.precompiled_contracts.modexp. +Require ethereum.gray_glacier.vm.precompiled_contracts.ripemd160. +Require ethereum.gray_glacier.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/modexp.ast b/coq/ethereum/gray_glacier/vm/precompiled_contracts/modexp.ast new file mode 100644 index 0000000000..42ecfa223f --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/modexp.ast @@ -0,0 +1,638 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `MODEXP` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + Assign( + targets=[ + Name(id='GQUADDIVISOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + FunctionDef( + name='modexp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and.\n `modulus`. The return value is the same length as the modulus.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='base_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_start', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Add(), + right=Name(id='base_length', ctx=Load()))), + Assign( + targets=[ + Name(id='exp_head', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Call( + func=Name(id='min', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='gas_cost', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load()), + Name(id='exp_length', ctx=Load()), + Name(id='exp_head', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='base_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='modulus_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Name(id='base_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_start', ctx=Store())], + value=BinOp( + left=Name(id='exp_start', ctx=Load()), + op=Add(), + right=Name(id='exp_length', ctx=Load()))), + Assign( + targets=[ + Name(id='modulus', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='modulus_start', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='modulus', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'\x00')], + keywords=[]), + op=Mult(), + right=Name(id='modulus_length', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exp', ctx=Load()), + Name(id='modulus', ctx=Load())], + keywords=[]), + attr='to_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[]), + Constant(value='big')], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='complexity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Estimate the complexity of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n Returns\n -------\n\n complexity : `Uint`\n Complexity of performing the operation.\n ')), + Assign( + targets=[ + Name(id='max_length', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load())], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Return( + value=BinOp( + left=Name(id='words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='iterations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the number of iterations required to perform a modular\n exponentiation.\n\n Parameters\n ----------\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n iterations : `Uint`\n Number of iterations.\n ')), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + Compare( + left=Name(id='exponent_head', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='bit_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='bit_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='bit_length', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Name(id='bit_length', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='length_part', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])))), + Assign( + targets=[ + Name(id='bits_part', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='bits_part', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='bits_part', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=BinOp( + left=Name(id='length_part', ctx=Load()), + op=Add(), + right=Name(id='bits_part', ctx=Load())))])]), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='count', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the gas cost of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n gas_cost : `Uint`\n Gas required for performing the operation.\n ')), + Assign( + targets=[ + Name(id='multiplication_complexity', ctx=Store())], + value=Call( + func=Name(id='complexity', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='iteration_count', ctx=Store())], + value=Call( + func=Name(id='iterations', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load()), + Name(id='exponent_head', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cost', ctx=Store())], + value=BinOp( + left=Name(id='multiplication_complexity', ctx=Load()), + op=Mult(), + right=Name(id='iteration_count', ctx=Load()))), + AugAssign( + target=Name(id='cost', ctx=Store()), + op=FloorDiv(), + value=Name(id='GQUADDIVISOR', ctx=Load())), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[]), + Name(id='cost', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/modexp.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000000..dd5605150e --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/modexp.v @@ -0,0 +1,236 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.gray_glacier.vm. +Require ethereum.gray_glacier.vm.gas. +Require ethereum.gray_glacier.vm.memory. + +Definition modexp (evm : Evm) : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "base_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "modulus_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "exp_head" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "min" |) ~(| + ethereum_types.numeric.U256 ~(| + 32 + |), + M.get_local ~(| "exp_length" |) + |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) ~(| + M.get_local ~(| "base_length" |), + M.get_local ~(| "modulus_length" |), + M.get_local ~(| "exp_length" |), + M.get_local ~(| "exp_head" |) + |) + |) ]] in + (* TODO statement *) + do* M.assign "base" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + M.get_local ~(| "base_length" |) + |) + |) in + ]] in + do* M.assign "exp" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "exp_length" |) + |) + |) in + ]] in + do* M.assign "modulus_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "modulus" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "modulus_start" |), + M.get_local ~(| "modulus_length" |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := + (* + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + *) + do* M.assign "max_length" [[ + M.get_local ~(| "max" |) ~(| + ethereum_types.numeric.Uint ~(| + base_length + |), + ethereum_types.numeric.Uint ~(| + modulus_length + |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition gas_cost (base_length : U256) (modulus_length : U256) (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + *) + do* M.assign "multiplication_complexity" [[ + M.get_local ~(| "complexity" |) ~(| + base_length, + modulus_length + |) in + ]] in + do* M.assign "iteration_count" [[ + M.get_local ~(| "iterations" |) ~(| + exponent_length, + exponent_head + |) in + ]] in + do* M.assign "cost" [[ + (* TODO expression *) in + ]] in + do* M.aug_assign [[ M.get_local ~(| "cost" |) ]] [[ + M.get_local ~(| "GQUADDIVISOR" |) + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/sha256.ast b/coq/ethereum/gray_glacier/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/precompiled_contracts/sha256.v b/coq/ethereum/gray_glacier/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/runtime.ast b/coq/ethereum/gray_glacier/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/runtime.v b/coq/ethereum/gray_glacier/vm/runtime.v new file mode 100644 index 0000000000..c8f96e69b4 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.gray_glacier.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/gray_glacier/vm/stack.ast b/coq/ethereum/gray_glacier/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/gray_glacier/vm/stack.v b/coq/ethereum/gray_glacier/vm/stack.v new file mode 100644 index 0000000000..11fb88ad79 --- /dev/null +++ b/coq/ethereum/gray_glacier/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.gray_glacier.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/homestead/__init__.ast b/coq/ethereum/homestead/__init__.ast new file mode 100644 index 0000000000..f8f4ba2fd2 --- /dev/null +++ b/coq/ethereum/homestead/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe Homestead fork increases the gas cost of creating contracts, restricts the\nrange of valid ECDSA signatures for transactions (but not precompiles), tweaks\nthe behavior of contract creation with insufficient gas, delays the\ndifficulty bomb, and adds an improved delegate call EVM instruction.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=1150000)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/__init__.v b/coq/ethereum/homestead/__init__.v new file mode 100644 index 0000000000..b212056d27 --- /dev/null +++ b/coq/ethereum/homestead/__init__.v @@ -0,0 +1,9 @@ +(* Generated *) +(* +The Homestead fork increases the gas cost of creating contracts, restricts the +range of valid ECDSA signatures for transactions (but not precompiles), tweaks +the behavior of contract creation with insufficient gas, delays the +difficulty bomb, and adds an improved delegate call EVM instruction. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/homestead/blocks.ast b/coq/ethereum/homestead/blocks.ast new file mode 100644 index 0000000000..dce2db5da0 --- /dev/null +++ b/coq/ethereum/homestead/blocks.ast @@ -0,0 +1,218 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mix_digest', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='post_state', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/blocks.v b/coq/ethereum/homestead/blocks.v new file mode 100644 index 0000000000..d9bce5f5a8 --- /dev/null +++ b/coq/ethereum/homestead/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.homestead.fork_types. +Require ethereum.homestead.transactions. diff --git a/coq/ethereum/homestead/bloom.ast b/coq/ethereum/homestead/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/homestead/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/bloom.v b/coq/ethereum/homestead/bloom.v new file mode 100644 index 0000000000..651168d395 --- /dev/null +++ b/coq/ethereum/homestead/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.homestead.blocks. +Require ethereum.homestead.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/homestead/fork.ast b/coq/ethereum/homestead/fork.ast new file mode 100644 index 0000000000..2305e94da0 --- /dev/null +++ b/coq/ethereum/homestead/fork.ast @@ -0,0 +1,2908 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.ethash', + names=[ + alias(name='dataset_size'), + alias(name='generate_cache'), + alias(name='hashimoto_light')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='create_ether'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='Transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BLOCK_REWARD', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=5), + op=Mult(), + right=BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=18)))], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=131072)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_OMMER_DEPTH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='validate_ommers', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='chain', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_difficulty', ctx=Store())], + value=Call( + func=Name(id='calculate_block_difficulty', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_difficulty', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='validate_proof_of_work', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generate_header_hash_for_pow', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate rlp hash of the header which is to be used for Proof-of-Work\n verification.\n\n In other words, the PoW artefacts `mix_digest` and `nonce` are ignored\n while calculating this hash.\n\n A particular PoW is valid for a single hash, that hash is computed by\n this function. The `nonce` and `mix_digest` are omitted from this hash\n because they are being changed by miners in their search for a sufficient\n proof-of-work.\n\n Parameters\n ----------\n header :\n The header object for which the hash is to be generated.\n\n Returns\n -------\n hash : `Hash32`\n The PoW valid rlp hash of the passed in header.\n ')), + Assign( + targets=[ + Name(id='header_data_without_pow_artefacts', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='state_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='transactions_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='receipt_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='bloom', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='header_data_without_pow_artefacts', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='validate_proof_of_work', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the Proof of Work constraints.\n\n In order to verify that a miner's proof-of-work is valid for a block, a\n ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``\n hash function. The mix digest is a hash of the header and the nonce that\n is passed through and it confirms whether or not proof-of-work was done\n on the correct block. The result is the actual hash value of the block.\n\n Parameters\n ----------\n header :\n Header of interest.\n ")), + Assign( + targets=[ + Name(id='header_hash', ctx=Store())], + value=Call( + func=Name(id='generate_header_hash_for_pow', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache', ctx=Store())], + value=Call( + func=Name(id='generate_cache', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='mix_digest', ctx=Store()), + Name(id='result', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='hashimoto_light', ctx=Load()), + args=[ + Name(id='header_hash', ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + Name(id='cache', ctx=Load()), + Call( + func=Name(id='dataset_size', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='mix_digest', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='mix_digest', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='limit', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='limit', ctx=Load()), + op=FloorDiv(), + right=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n gas_available :\n The gas remaining in the block.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + Return( + value=Name(id='sender_address', ctx=Load()))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='post_state', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n post_state :\n The state root immediately after this transaction.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='post_state', + value=Name(id='post_state', ctx=Load())), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + Return( + value=Name(id='receipt', ctx=Load()))], + decorator_list=[], + returns=Name(id='Receipt', ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='block_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n block_difficulty :\n Difficulty of the block.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='transactions', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='tx', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='gas_available', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='gas_price', + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='difficulty', + value=Name(id='block_difficulty', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[]), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='pay_rewards', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='block_number', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='ommers', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='validate_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='block_header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the ommers mentioned in the block.\n\n An ommer block is a block that wasn't canonically added to the\n blockchain because it wasn't validated as fast as the canonical block\n but was mined at the same time.\n\n To be considered valid, the ommers must adhere to the rules defined in\n the Ethereum protocol. The maximum amount of ommers is 2 per block and\n there cannot be duplicate ommers in a block. Many of the other ommer\n constraints are listed in the in-line comments of this function.\n\n Parameters\n ----------\n ommers :\n List of ommers mentioned in the current block.\n block_header:\n The header of current block.\n chain :\n History and current state.\n ")), + Assign( + targets=[ + Name(id='block_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='block_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='ommers_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return()], + orelse=[]), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + op=Sub(), + right=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Name(id='ommer', ctx=Load()), + Name(id='ommer_parent_header', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=2)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommers_hashes', ctx=Store())], + value=ListComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + ifs=[], + is_async=0)])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[])], + keywords=[])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_canonical_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=BinOp( + left=Name(id='MAX_OMMER_DEPTH', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + ctx=Load())), + Assign( + targets=[ + Name(id='recent_canonical_block_hashes', ctx=Store())], + value=SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='recent_ommers_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + simple=1), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='recent_ommers_hashes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='recent_ommers_hashes', ctx=Load()), + attr='union', + ctx=Load()), + args=[ + SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='ommer_index', ctx=Store()), + Name(id='ommer', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='ommer_hash', ctx=Store())], + value=Subscript( + value=Name(id='ommers_hashes', ctx=Load()), + slice=Name(id='ommer_index', ctx=Load()), + ctx=Load())), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='block_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_ommers_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='ommer_age', ctx=Load())]), + Compare( + left=Name(id='ommer_age', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_OMMER_DEPTH', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='parent_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pay_rewards', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pay rewards to the block miner as well as the ommers miners.\n\n The miner of the canonical block is rewarded with the predetermined\n block reward, ``BLOCK_REWARD``, plus a variable award based off of the\n number of ommer blocks that were mined around the same time, and included\n in the canonical block's header. An ommer block is a block that wasn't\n added to the canonical blockchain because it wasn't validated as fast as\n the accepted block but was mined at the same time. Although not all blocks\n that are mined are added to the canonical chain, miners are still paid a\n reward for their efforts. This reward is called an ommer reward and is\n calculated based on the number associated with the ommer block that they\n mined.\n\n Parameters\n ----------\n state :\n Current account state.\n block_number :\n Position of the block within the chain.\n coinbase :\n Address of account which receives block reward and transaction fees.\n ommers :\n List of ommers mentioned in the current block.\n ")), + Assign( + targets=[ + Name(id='ommer_count', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='miner_reward', ctx=Store())], + value=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='ommer_count', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='miner_reward', ctx=Load())], + keywords=[])), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_number', ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='ommer_miner_reward', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Sub(), + right=Name(id='ommer_age', ctx=Load())), + op=Mult(), + right=Name(id='BLOCK_REWARD', ctx=Load())), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='ommer_miner_reward', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[])), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Name(id='TX_CREATE_COST', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='v', ctx=Store()), + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=28)])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Compute the hash of a transaction used in the signature.\n\n The values that are used to compute the signing hash set the rules for a\n transaction. For example, signing over the gas sets a limit for the\n amount of money that is allowed to be pulled out of the sender's account.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_difficulty', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes difficulty of a block using its header and parent header.\n\n The difficulty is determined by the time the block was created after its\n parent. The ``offset`` is calculated using the parent block's difficulty,\n ``parent_difficulty``, and the timestamp between blocks. This offset is\n then added to the parent difficulty and is stored as the ``difficulty``\n variable. If the time between the block and its parent is too short, the\n offset will result in a positive number thus making the sum of\n ``parent_difficulty`` and ``offset`` to be a greater value in order to\n avoid mass forking. But, if the time is long enough, then the offset\n results in a negative value making the block less difficult than\n its parent.\n\n The base standard for a block's difficulty is the predefined value\n set for the genesis block since it has no parent. So, a block\n can't be less difficult than the genesis block, therefore each block's\n difficulty is set to the maximum value between the calculated\n difficulty and the ``GENESIS_DIFFICULTY``.\n\n Parameters\n ----------\n block_number :\n Block number of the block.\n block_timestamp :\n Timestamp of the block.\n parent_timestamp :\n Timestamp of the parent block.\n parent_difficulty :\n difficulty of the parent block.\n\n Returns\n -------\n difficulty : `ethereum.base_types.Uint`\n Computed difficulty for a block.\n ")), + Assign( + targets=[ + Name(id='offset', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=2048)), + op=Mult(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=Constant(value=1), + op=Sub(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_timestamp', ctx=Load()), + op=Sub(), + right=Name(id='parent_timestamp', ctx=Load()))], + keywords=[]), + op=FloorDiv(), + right=Constant(value=10))), + UnaryOp( + op=USub(), + operand=Constant(value=99))], + keywords=[]))), + Assign( + targets=[ + Name(id='difficulty', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='offset', ctx=Load()))), + Assign( + targets=[ + Name(id='num_bomb_periods', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=100000)), + op=Sub(), + right=Constant(value=2))), + If( + test=Compare( + left=Name(id='num_bomb_periods', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='difficulty', ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Name(id='num_bomb_periods', ctx=Load())))], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='difficulty', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/fork.v b/coq/ethereum/homestead/fork.v new file mode 100644 index 0000000000..0da6d386d2 --- /dev/null +++ b/coq/ethereum/homestead/fork.v @@ -0,0 +1,831 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.ethash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.homestead.__init__. +Require ethereum.homestead.blocks. +Require ethereum.homestead.bloom. +Require ethereum.homestead.fork_types. +Require ethereum.homestead.state. +Require ethereum.homestead.transactions. +Require ethereum.homestead.trie. +Require ethereum.homestead.utils.message. +Require ethereum.homestead.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + do* [[ M.get_local ~(| "validate_ommers" |) ~(| + M.get_field ~(| block, "ommers" |), + M.get_field ~(| block, "header" |), + chain + |) ]] in + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "difficulty" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| block, "ommers" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_difficulty" [[ + M.get_local ~(| "calculate_block_difficulty" |) ~(| + M.get_field ~(| header, "number" |), + M.get_field ~(| header, "timestamp" |), + M.get_field ~(| parent_header, "timestamp" |), + M.get_field ~(| parent_header, "difficulty" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| + header + |) ]] in + M.pure tt. + +Definition generate_header_hash_for_pow (header : Header) : M Hash32 := + (* + 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. + *) + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_proof_of_work (header : Header) : M unit := + (* + 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. + *) + do* M.assign "header_hash" [[ + M.get_local ~(| "generate_header_hash_for_pow" |) ~(| + header + |) in + ]] in + do* M.assign "cache" [[ + ethereum.ethash.generate_cache ~(| + M.get_field ~(| header, "number" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (gas_available : Uint) : M 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. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + tx + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (post_state : Bytes32) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (block_gas_limit : Uint) (block_time : U256) (block_difficulty : Uint) (transactions : (* TODO type *)) (ommers : (* TODO type *)) : M ApplyBodyOutput := + (* + 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 + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "pay_rewards" |) ~(| + state, + block_number, + coinbase, + ommers + |) ]] in + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_ommers (ommers : (* TODO type *)) (block_header : Header) (chain : BlockChain) : M unit := + (* + 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. + *) + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_canonical_blocks" [[ + (* TODO expression *) in + ]] in + do* M.assign "recent_canonical_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition pay_rewards (state : State) (block_number : Uint) (coinbase : Address) (ommers : (* TODO type *)) : M unit := + (* + 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. + *) + do* M.assign "ommer_count" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + ommers + |) + |) in + ]] in + do* M.assign "miner_reward" [[ + (* TODO expression *) in + ]] in + do* [[ state.create_ether ~(| + state, + coinbase, + M.get_local ~(| "miner_reward" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + do* M.assign "gas_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| env, "coinbase" |), + M.get_local ~(| "coinbase_balance_after_mining_fee" |) + |) ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "public_key" [[ + ethereum.crypto.elliptic_curve.secp256k1_recover ~(| + M.get_local ~(| "r" |), + M.get_local ~(| "s" |), + (* TODO expression *), + M.get_local ~(| "signing_hash" |) ~(| + tx + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition signing_hash (tx : Transaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_block_difficulty (block_number : Uint) (block_timestamp : U256) (parent_timestamp : U256) (parent_difficulty : Uint) : M Uint := + (* + 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. + *) + do* M.assign "offset" [[ + (* TODO expression *) in + ]] in + do* M.assign "difficulty" [[ + (* TODO expression *) in + ]] in + do* M.assign "num_bomb_periods" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/homestead/fork_types.ast b/coq/ethereum/homestead/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/homestead/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/fork_types.v b/coq/ethereum/homestead/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/homestead/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/homestead/state.ast b/coq/ethereum/homestead/state.ast new file mode 100644 index 0000000000..dce2e294a9 --- /dev/null +++ b/coq/ethereum/homestead/state.ast @@ -0,0 +1,1292 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add newly created ether to an account.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to which ether is added.\n amount:\n The amount of ether to be added to the account of interest.\n ')), + FunctionDef( + name='increase_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/state.v b/coq/ethereum/homestead/state.v new file mode 100644 index 0000000000..ca861a3cb9 --- /dev/null +++ b/coq/ethereum/homestead/state.v @@ -0,0 +1,484 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.homestead.fork_types. +Require ethereum.homestead.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := + (* + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/transactions.ast b/coq/ethereum/homestead/transactions.ast new file mode 100644 index 0000000000..19d5c9707f --- /dev/null +++ b/coq/ethereum/homestead/transactions.ast @@ -0,0 +1,106 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + ClassDef( + name='Transaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/transactions.v b/coq/ethereum/homestead/transactions.v new file mode 100644 index 0000000000..797f9426b7 --- /dev/null +++ b/coq/ethereum/homestead/transactions.v @@ -0,0 +1,13 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.homestead.fork_types. diff --git a/coq/ethereum/homestead/trie.ast b/coq/ethereum/homestead/trie.ast new file mode 100644 index 0000000000..73356f4045 --- /dev/null +++ b/coq/ethereum/homestead/trie.ast @@ -0,0 +1,1618 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.frontier', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.RLP`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/trie.v b/coq/ethereum/homestead/trie.v new file mode 100644 index 0000000000..6b8953f256 --- /dev/null +++ b/coq/ethereum/homestead/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/homestead/utils/__init__.ast b/coq/ethereum/homestead/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/homestead/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/utils/__init__.v b/coq/ethereum/homestead/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/homestead/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/homestead/utils/address.ast b/coq/ethereum/homestead/utils/address.ast new file mode 100644 index 0000000000..620e03a4a0 --- /dev/null +++ b/coq/ethereum/homestead/utils/address.ast @@ -0,0 +1,139 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this homestead version of specification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `ethereum.homestead.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/utils/address.v b/coq/ethereum/homestead/utils/address.v new file mode 100644 index 0000000000..36fb655fbc --- /dev/null +++ b/coq/ethereum/homestead/utils/address.v @@ -0,0 +1,74 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this homestead version of specification. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.homestead.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.homestead.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/homestead/utils/hexadecimal.ast b/coq/ethereum/homestead/utils/hexadecimal.ast new file mode 100644 index 0000000000..d9a7fc8a53 --- /dev/null +++ b/coq/ethereum/homestead/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to Homestead\ntypes.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/utils/hexadecimal.v b/coq/ethereum/homestead/utils/hexadecimal.v new file mode 100644 index 0000000000..1c2f22a801 --- /dev/null +++ b/coq/ethereum/homestead/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to Homestead +types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.homestead.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/homestead/utils/message.ast b/coq/ethereum/homestead/utils/message.ast new file mode 100644 index 0000000000..38628216f0 --- /dev/null +++ b/coq/ethereum/homestead/utils/message.ast @@ -0,0 +1,234 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this homestead version of specification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True)]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n\n Returns\n -------\n message: `ethereum.homestead.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/utils/message.v b/coq/ethereum/homestead/utils/message.v new file mode 100644 index 0000000000..dbf5563f9b --- /dev/null +++ b/coq/ethereum/homestead/utils/message.v @@ -0,0 +1,56 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this homestead version of specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.homestead.fork_types. +Require ethereum.homestead.state. +Require ethereum.homestead.vm. +Require ethereum.homestead.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + + Returns + ------- + message: `ethereum.homestead.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/homestead/vm/__init__.ast b/coq/ethereum/homestead/vm/__init__.ast new file mode 100644 index 0000000000..b679ec6d01 --- /dev/null +++ b/coq/ethereum/homestead/vm/__init__.ast @@ -0,0 +1,362 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State')], + level=2), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/__init__.v b/coq/ethereum/homestead/vm/__init__.v new file mode 100644 index 0000000000..733993a8d3 --- /dev/null +++ b/coq/ethereum/homestead/vm/__init__.v @@ -0,0 +1,65 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.homestead.blocks. +Require ethereum.homestead.fork_types. +Require ethereum.homestead.state. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/vm/exceptions.ast b/coq/ethereum/homestead/vm/exceptions.ast new file mode 100644 index 0000000000..3194c3c232 --- /dev/null +++ b/coq/ethereum/homestead/vm/exceptions.ast @@ -0,0 +1,125 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/exceptions.v b/coq/ethereum/homestead/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/homestead/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/homestead/vm/gas.ast b/coq/ethereum/homestead/vm/gas.ast new file mode 100644 index 0000000000..675fef92a5 --- /dev/null +++ b/coq/ethereum/homestead/vm/gas.ast @@ -0,0 +1,759 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists')], + level=2), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXTERNAL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BALANCE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=40)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='REFUND_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=24000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount for executing Opcodes `CALL` and `CALLCODE`.\n\n Parameters\n ----------\n state :\n The current state.\n gas :\n The amount of gas provided to the message-call.\n to:\n The address of the recipient account.\n value:\n The amount of `ETH` that needs to be transferred.\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='gas', ctx=Load())), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))), + Assign( + targets=[ + Name(id='stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Name(id='gas', ctx=Load()), + orelse=BinOp( + left=Name(id='GAS_CALL_STIPEND', ctx=Load()), + op=Add(), + right=Name(id='gas', ctx=Load())))), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + Name(id='cost', ctx=Load()), + Name(id='stipend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/gas.v b/coq/ethereum/homestead/vm/gas.v new file mode 100644 index 0000000000..555e3a9b77 --- /dev/null +++ b/coq/ethereum/homestead/vm/gas.v @@ -0,0 +1,149 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.homestead.fork_types. +Require ethereum.homestead.state. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (state : State) (gas : Uint) (to : Address) (value : U256) : M MessageCallGas := + (* + Calculates the gas amount for executing Opcodes `CALL` and `CALLCODE`. + + Parameters + ---------- + state : + The current state. + gas : + The amount of gas provided to the message-call. + to: + The address of the recipient account. + value: + The amount of `ETH` that needs to be transferred. + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/homestead/vm/instructions/__init__.ast b/coq/ethereum/homestead/vm/instructions/__init__.ast new file mode 100644 index 0000000000..0931c390c8 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/__init__.ast @@ -0,0 +1,1648 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='DIFFICULTY', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIFFICULTY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/instructions/__init__.v b/coq/ethereum/homestead/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/homestead/vm/instructions/arithmetic.ast b/coq/ethereum/homestead/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/instructions/arithmetic.v b/coq/ethereum/homestead/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..2bbaf77a26 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/vm/instructions/bitwise.ast b/coq/ethereum/homestead/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..73dc9f4a45 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/bitwise.ast @@ -0,0 +1,418 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/instructions/bitwise.v b/coq/ethereum/homestead/vm/instructions/bitwise.v new file mode 100644 index 0000000000..8682c0544e --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/bitwise.v @@ -0,0 +1,196 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/vm/instructions/block.ast b/coq/ethereum/homestead/vm/instructions/block.ast new file mode 100644 index 0000000000..cc66857e82 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/block.ast @@ -0,0 +1,437 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's difficulty onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/instructions/block.v b/coq/ethereum/homestead/vm/instructions/block.v new file mode 100644 index 0000000000..13153fbbcf --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/block.v @@ -0,0 +1,213 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition difficulty (evm : Evm) : M unit := + (* + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/vm/instructions/comparison.ast b/coq/ethereum/homestead/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/instructions/comparison.v b/coq/ethereum/homestead/vm/instructions/comparison.v new file mode 100644 index 0000000000..072b6a631f --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/vm/instructions/control_flow.ast b/coq/ethereum/homestead/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/instructions/control_flow.v b/coq/ethereum/homestead/vm/instructions/control_flow.v new file mode 100644 index 0000000000..77e0597fd7 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.exceptions. +Require ethereum.homestead.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/vm/instructions/environment.ast b/coq/ethereum/homestead/vm/instructions/environment.ast new file mode 100644 index 0000000000..15f88ad9cc --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/environment.ast @@ -0,0 +1,1199 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BALANCE'), + alias(name='GAS_BASE'), + alias(name='GAS_COPY'), + alias(name='GAS_EXTERNAL'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BALANCE', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_EXTERNAL', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_EXTERNAL', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/instructions/environment.v b/coq/ethereum/homestead/vm/instructions/environment.v new file mode 100644 index 0000000000..ea707d042c --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/environment.v @@ -0,0 +1,552 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.homestead.state. +Require ethereum.homestead.utils.address. +Require ethereum.homestead.vm.memory. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BALANCE + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_EXTERNAL + |) ]] in + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/vm/instructions/keccak.ast b/coq/ethereum/homestead/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/instructions/keccak.v b/coq/ethereum/homestead/vm/instructions/keccak.v new file mode 100644 index 0000000000..577c4f3b50 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.memory. +Require ethereum.homestead.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/vm/instructions/log.ast b/coq/ethereum/homestead/vm/instructions/log.ast new file mode 100644 index 0000000000..d3bf292c44 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/log.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/instructions/log.v b/coq/ethereum/homestead/vm/instructions/log.v new file mode 100644 index 0000000000..92657d71fa --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/log.v @@ -0,0 +1,77 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.homestead.blocks. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.memory. +Require ethereum.homestead.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/vm/instructions/memory.ast b/coq/ethereum/homestead/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/instructions/memory.v b/coq/ethereum/homestead/vm/instructions/memory.v new file mode 100644 index 0000000000..c5a4e7abe3 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.memory. +Require ethereum.homestead.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/vm/instructions/stack.ast b/coq/ethereum/homestead/vm/instructions/stack.ast new file mode 100644 index 0000000000..95cfc0b6cf --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/stack.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/instructions/stack.v b/coq/ethereum/homestead/vm/instructions/stack.v new file mode 100644 index 0000000000..e5a9c2d19c --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/stack.v @@ -0,0 +1,153 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.exceptions. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/vm/instructions/storage.ast b/coq/ethereum/homestead/vm/instructions/storage.ast new file mode 100644 index 0000000000..7ce9b2f17f --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/storage.ast @@ -0,0 +1,278 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_SLOAD', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_UPDATE', ctx=Load()))]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/instructions/storage.v b/coq/ethereum/homestead/vm/instructions/storage.v new file mode 100644 index 0000000000..d5370c8953 --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/storage.v @@ -0,0 +1,108 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.homestead.state. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_SLOAD + |) ]] in + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/vm/instructions/system.ast b/coq/ethereum/homestead/vm/instructions/system.ast new file mode 100644 index 0000000000..91e4fc3a4a --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/system.ast @@ -0,0 +1,1863 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL'), + alias(name='GAS_CREATE'), + alias(name='GAS_ZERO'), + alias(name='REFUND_SELF_DESTRUCT'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])])]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_ZERO', ctx=Load())), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='refunded_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load())), + While( + test=Compare( + left=Name(id='parent_evm', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='refunded_accounts', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='originator', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='refunded_accounts', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='REFUND_SELF_DESTRUCT', ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='gas', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/instructions/system.v b/coq/ethereum/homestead/vm/instructions/system.v new file mode 100644 index 0000000000..4759fcae3c --- /dev/null +++ b/coq/ethereum/homestead/vm/instructions/system.v @@ -0,0 +1,487 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.homestead.fork_types. +Require ethereum.homestead.state. +Require ethereum.homestead.utils.address. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.memory. +Require ethereum.homestead.vm.stack. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "create_message_gas" [[ + M.get_field ~(| evm, "gas_left" |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "gas" |), + M.get_local ~(| "to" |), + M.get_local ~(| "value" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "gas" |), + M.get_local ~(| "to" |), + M.get_local ~(| "value" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_ZERO in + ]] in + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "refunded_accounts" [[ + M.get_field ~(| evm, "accounts_to_delete" |) in + ]] in + do* M.assign "parent_evm" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "parent_evm" |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_local ~(| "gas" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/homestead/vm/interpreter.ast b/coq/ethereum/homestead/vm/interpreter.ast new file mode 100644 index 0000000000..440d30e472 --- /dev/null +++ b/coq/ethereum/homestead/vm/interpreter.ast @@ -0,0 +1,975 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidOpcode'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.homestead.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.homestead.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='error', + value=Constant(value=None))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/interpreter.v b/coq/ethereum/homestead/vm/interpreter.v new file mode 100644 index 0000000000..7ca9baf48e --- /dev/null +++ b/coq/ethereum/homestead/vm/interpreter.v @@ -0,0 +1,165 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.homestead.blocks. +Require ethereum.homestead.fork_types. +Require ethereum.homestead.state. +Require ethereum.homestead.vm. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.precompiled_contracts.mapping. +Require ethereum.homestead.vm.__init__. +Require ethereum.homestead.vm.exceptions. +Require ethereum.homestead.vm.instructions. +Require ethereum.homestead.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.homestead.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.homestead.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/homestead/vm/memory.ast b/coq/ethereum/homestead/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/homestead/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/memory.v b/coq/ethereum/homestead/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/homestead/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/__init__.ast b/coq/ethereum/homestead/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..2ac4916772 --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,52 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/__init__.v b/coq/ethereum/homestead/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..2a101b8e64 --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.homestead.utils.hexadecimal. diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/homestead/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/homestead/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..7da8669e4f --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.homestead.vm. +Require ethereum.homestead.vm.gas. +Require ethereum.homestead.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/identity.ast b/coq/ethereum/homestead/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/identity.v b/coq/ethereum/homestead/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..2a556b5d08 --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.homestead.vm. +Require ethereum.homestead.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/mapping.ast b/coq/ethereum/homestead/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..de162645ff --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,65 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/mapping.v b/coq/ethereum/homestead/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..82ffcb5b5a --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/mapping.v @@ -0,0 +1,22 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.homestead.fork_types. +Require ethereum.homestead.vm.precompiled_contracts.__init__. +Require ethereum.homestead.vm.precompiled_contracts.ecrecover. +Require ethereum.homestead.vm.precompiled_contracts.identity. +Require ethereum.homestead.vm.precompiled_contracts.ripemd160. +Require ethereum.homestead.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/homestead/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/homestead/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/sha256.ast b/coq/ethereum/homestead/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/precompiled_contracts/sha256.v b/coq/ethereum/homestead/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/homestead/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/homestead/vm/runtime.ast b/coq/ethereum/homestead/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/homestead/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/runtime.v b/coq/ethereum/homestead/vm/runtime.v new file mode 100644 index 0000000000..9810c1185c --- /dev/null +++ b/coq/ethereum/homestead/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.homestead.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/homestead/vm/stack.ast b/coq/ethereum/homestead/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/homestead/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/homestead/vm/stack.v b/coq/ethereum/homestead/vm/stack.v new file mode 100644 index 0000000000..07328e37af --- /dev/null +++ b/coq/ethereum/homestead/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.homestead.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/__init__.ast b/coq/ethereum/istanbul/__init__.ast new file mode 100644 index 0000000000..6b171b467b --- /dev/null +++ b/coq/ethereum/istanbul/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe Istanbul fork makes changes to the gas costs of EVM instructions and data,\nadds a cryptographic primitive, and introduces an instruction to fetch the\ncurrent chain identifier.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=9069000)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/__init__.v b/coq/ethereum/istanbul/__init__.v new file mode 100644 index 0000000000..87e3cb056d --- /dev/null +++ b/coq/ethereum/istanbul/__init__.v @@ -0,0 +1,8 @@ +(* Generated *) +(* +The Istanbul fork makes changes to the gas costs of EVM instructions and data, +adds a cryptographic primitive, and introduces an instruction to fetch the +current chain identifier. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/istanbul/blocks.ast b/coq/ethereum/istanbul/blocks.ast new file mode 100644 index 0000000000..bcca95bdaa --- /dev/null +++ b/coq/ethereum/istanbul/blocks.ast @@ -0,0 +1,218 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mix_digest', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='succeeded', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/blocks.v b/coq/ethereum/istanbul/blocks.v new file mode 100644 index 0000000000..317be6c28f --- /dev/null +++ b/coq/ethereum/istanbul/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.istanbul.fork_types. +Require ethereum.istanbul.transactions. diff --git a/coq/ethereum/istanbul/bloom.ast b/coq/ethereum/istanbul/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/istanbul/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/bloom.v b/coq/ethereum/istanbul/bloom.v new file mode 100644 index 0000000000..28d3227f1a --- /dev/null +++ b/coq/ethereum/istanbul/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.istanbul.blocks. +Require ethereum.istanbul.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/fork.ast b/coq/ethereum/istanbul/fork.ast new file mode 100644 index 0000000000..301fddac17 --- /dev/null +++ b/coq/ethereum/istanbul/fork.ast @@ -0,0 +1,3189 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.ethash', + names=[ + alias(name='dataset_size'), + alias(name='generate_cache'), + alias(name='hashimoto_light')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty'), + alias(name='create_ether'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='Transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BLOCK_REWARD', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=18)))], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=131072)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_OMMER_DEPTH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='BOMB_DELAY_BLOCKS', ctx=Store())], + value=Constant(value=5000000)), + Assign( + targets=[ + Name(id='EMPTY_OMMER_HASH', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List(elts=[], ctx=Load())], + keywords=[])], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='validate_ommers', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='chain', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='chain', ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + Assign( + targets=[ + Name(id='parent_has_ommers', ctx=Store())], + value=Compare( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='EMPTY_OMMER_HASH', ctx=Load())])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_difficulty', ctx=Store())], + value=Call( + func=Name(id='calculate_block_difficulty', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Name(id='parent_has_ommers', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_difficulty', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='validate_proof_of_work', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generate_header_hash_for_pow', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate rlp hash of the header which is to be used for Proof-of-Work\n verification.\n\n In other words, the PoW artefacts `mix_digest` and `nonce` are ignored\n while calculating this hash.\n\n A particular PoW is valid for a single hash, that hash is computed by\n this function. The `nonce` and `mix_digest` are omitted from this hash\n because they are being changed by miners in their search for a sufficient\n proof-of-work.\n\n Parameters\n ----------\n header :\n The header object for which the hash is to be generated.\n\n Returns\n -------\n hash : `Hash32`\n The PoW valid rlp hash of the passed in header.\n ')), + Assign( + targets=[ + Name(id='header_data_without_pow_artefacts', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='state_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='transactions_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='receipt_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='bloom', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='header_data_without_pow_artefacts', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='validate_proof_of_work', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the Proof of Work constraints.\n\n In order to verify that a miner's proof-of-work is valid for a block, a\n ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``\n hash function. The mix digest is a hash of the header and the nonce that\n is passed through and it confirms whether or not proof-of-work was done\n on the correct block. The result is the actual hash value of the block.\n\n Parameters\n ----------\n header :\n Header of interest.\n ")), + Assign( + targets=[ + Name(id='header_hash', ctx=Store())], + value=Call( + func=Name(id='generate_header_hash_for_pow', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache', ctx=Store())], + value=Call( + func=Name(id='generate_cache', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='mix_digest', ctx=Store()), + Name(id='result', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='hashimoto_light', ctx=Load()), + args=[ + Name(id='header_hash', ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + Name(id='cache', ctx=Load()), + Call( + func=Name(id='dataset_size', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='mix_digest', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='mix_digest', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='limit', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='limit', ctx=Load()), + op=FloorDiv(), + right=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n gas_available :\n The gas remaining in the block.\n chain_id :\n The ID of the current chain.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + Return( + value=Name(id='sender_address', ctx=Load()))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='error', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n error :\n Error in the top level frame of the transaction, if any.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='succeeded', + value=Compare( + left=Name(id='error', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)])), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + Return( + value=Name(id='receipt', ctx=Load()))], + decorator_list=[], + returns=Name(id='Receipt', ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='block_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n block_difficulty :\n Difficulty of the block.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='transactions', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='tx', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='gas_available', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='gas_price', + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='difficulty', + value=Name(id='block_difficulty', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='chain_id', + value=Name(id='chain_id', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store()), + Name(id='error', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='error', ctx=Load()), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='pay_rewards', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='block_number', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='ommers', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='validate_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='block_header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the ommers mentioned in the block.\n\n An ommer block is a block that wasn't canonically added to the\n blockchain because it wasn't validated as fast as the canonical block\n but was mined at the same time.\n\n To be considered valid, the ommers must adhere to the rules defined in\n the Ethereum protocol. The maximum amount of ommers is 2 per block and\n there cannot be duplicate ommers in a block. Many of the other ommer\n constraints are listed in the in-line comments of this function.\n\n Parameters\n ----------\n ommers :\n List of ommers mentioned in the current block.\n block_header:\n The header of current block.\n chain :\n History and current state.\n ")), + Assign( + targets=[ + Name(id='block_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='block_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='ommers_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return()], + orelse=[]), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + op=Sub(), + right=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Name(id='ommer', ctx=Load()), + Name(id='ommer_parent_header', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=2)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommers_hashes', ctx=Store())], + value=ListComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + ifs=[], + is_async=0)])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[])], + keywords=[])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_canonical_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=BinOp( + left=Name(id='MAX_OMMER_DEPTH', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + ctx=Load())), + Assign( + targets=[ + Name(id='recent_canonical_block_hashes', ctx=Store())], + value=SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='recent_ommers_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + simple=1), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='recent_ommers_hashes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='recent_ommers_hashes', ctx=Load()), + attr='union', + ctx=Load()), + args=[ + SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='ommer_index', ctx=Store()), + Name(id='ommer', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='ommer_hash', ctx=Store())], + value=Subscript( + value=Name(id='ommers_hashes', ctx=Load()), + slice=Name(id='ommer_index', ctx=Load()), + ctx=Load())), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='block_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_ommers_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='ommer_age', ctx=Load())]), + Compare( + left=Name(id='ommer_age', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_OMMER_DEPTH', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='parent_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pay_rewards', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pay rewards to the block miner as well as the ommers miners.\n\n The miner of the canonical block is rewarded with the predetermined\n block reward, ``BLOCK_REWARD``, plus a variable award based off of the\n number of ommer blocks that were mined around the same time, and included\n in the canonical block's header. An ommer block is a block that wasn't\n added to the canonical blockchain because it wasn't validated as fast as\n the accepted block but was mined at the same time. Although not all blocks\n that are mined are added to the canonical chain, miners are still paid a\n reward for their efforts. This reward is called an ommer reward and is\n calculated based on the number associated with the ommer block that they\n mined.\n\n Parameters\n ----------\n state :\n Current account state.\n block_number :\n Position of the block within the chain.\n coinbase :\n Address of account which receives block reward and transaction fees.\n ommers :\n List of ommers mentioned in the current block.\n ")), + Assign( + targets=[ + Name(id='ommer_count', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='miner_reward', ctx=Store())], + value=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='ommer_count', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='miner_reward', ctx=Load())], + keywords=[])), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_number', ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='ommer_miner_reward', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Sub(), + right=Name(id='ommer_age', ctx=Load())), + op=Mult(), + right=Name(id='BLOCK_REWARD', ctx=Load())), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='ommer_miner_reward', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + If( + test=Compare( + left=Name(id='coinbase_balance_after_mining_fee', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]))], + orelse=[])]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='error', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Name(id='TX_CREATE_COST', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='v', ctx=Store()), + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=28)])]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash_pre155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='chain_id_x2', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=36)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[])), + op=Sub(), + right=Name(id='chain_id_x2', ctx=Load())), + Call( + func=Name(id='signing_hash_155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])], + keywords=[]))]), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash_pre155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a legacy (pre EIP 155) signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 155 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n The id of the current chain.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='chain_id', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_has_ommers', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes difficulty of a block using its header and parent header.\n\n The difficulty is determined by the time the block was created after its\n parent. The ``offset`` is calculated using the parent block's difficulty,\n ``parent_difficulty``, and the timestamp between blocks. This offset is\n then added to the parent difficulty and is stored as the ``difficulty``\n variable. If the time between the block and its parent is too short, the\n offset will result in a positive number thus making the sum of\n ``parent_difficulty`` and ``offset`` to be a greater value in order to\n avoid mass forking. But, if the time is long enough, then the offset\n results in a negative value making the block less difficult than\n its parent.\n\n The base standard for a block's difficulty is the predefined value\n set for the genesis block since it has no parent. So, a block\n can't be less difficult than the genesis block, therefore each block's\n difficulty is set to the maximum value between the calculated\n difficulty and the ``GENESIS_DIFFICULTY``.\n\n Parameters\n ----------\n block_number :\n Block number of the block.\n block_timestamp :\n Timestamp of the block.\n parent_timestamp :\n Timestamp of the parent block.\n parent_difficulty :\n difficulty of the parent block.\n parent_has_ommers:\n does the parent have ommers.\n\n Returns\n -------\n difficulty : `ethereum.base_types.Uint`\n Computed difficulty for a block.\n ")), + Assign( + targets=[ + Name(id='offset', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=2048)), + op=Mult(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=IfExp( + test=Name(id='parent_has_ommers', ctx=Load()), + body=Constant(value=2), + orelse=Constant(value=1)), + op=Sub(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_timestamp', ctx=Load()), + op=Sub(), + right=Name(id='parent_timestamp', ctx=Load()))], + keywords=[]), + op=FloorDiv(), + right=Constant(value=9))), + UnaryOp( + op=USub(), + operand=Constant(value=99))], + keywords=[]))), + Assign( + targets=[ + Name(id='difficulty', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='offset', ctx=Load()))), + Assign( + targets=[ + Name(id='num_bomb_periods', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='BOMB_DELAY_BLOCKS', ctx=Load())), + op=FloorDiv(), + right=Constant(value=100000)), + op=Sub(), + right=Constant(value=2))), + If( + test=Compare( + left=Name(id='num_bomb_periods', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='difficulty', ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Name(id='num_bomb_periods', ctx=Load())))], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='difficulty', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/fork.v b/coq/ethereum/istanbul/fork.v new file mode 100644 index 0000000000..a315352ef1 --- /dev/null +++ b/coq/ethereum/istanbul/fork.v @@ -0,0 +1,847 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.ethash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.istanbul.__init__. +Require ethereum.istanbul.blocks. +Require ethereum.istanbul.bloom. +Require ethereum.istanbul.fork_types. +Require ethereum.istanbul.state. +Require ethereum.istanbul.transactions. +Require ethereum.istanbul.trie. +Require ethereum.istanbul.utils.message. +Require ethereum.istanbul.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + do* [[ M.get_local ~(| "validate_ommers" |) ~(| + M.get_field ~(| block, "ommers" |), + M.get_field ~(| block, "header" |), + chain + |) ]] in + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "difficulty" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| block, "ommers" |), + M.get_field ~(| chain, "chain_id" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + do* M.assign "parent_has_ommers" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_difficulty" [[ + M.get_local ~(| "calculate_block_difficulty" |) ~(| + M.get_field ~(| header, "number" |), + M.get_field ~(| header, "timestamp" |), + M.get_field ~(| parent_header, "timestamp" |), + M.get_field ~(| parent_header, "difficulty" |), + M.get_local ~(| "parent_has_ommers" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| + header + |) ]] in + M.pure tt. + +Definition generate_header_hash_for_pow (header : Header) : M Hash32 := + (* + 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. + *) + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_proof_of_work (header : Header) : M unit := + (* + 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. + *) + do* M.assign "header_hash" [[ + M.get_local ~(| "generate_header_hash_for_pow" |) ~(| + header + |) in + ]] in + do* M.assign "cache" [[ + ethereum.ethash.generate_cache ~(| + M.get_field ~(| header, "number" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (gas_available : Uint) (chain_id : U64) : M Address := + (* + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (error : (* TODO type *)) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (block_gas_limit : Uint) (block_time : U256) (block_difficulty : Uint) (transactions : (* TODO type *)) (ommers : (* TODO type *)) (chain_id : U64) : M ApplyBodyOutput := + (* + 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.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "pay_rewards" |) ~(| + state, + block_number, + coinbase, + ommers + |) ]] in + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_ommers (ommers : (* TODO type *)) (block_header : Header) (chain : BlockChain) : M unit := + (* + 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. + *) + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_canonical_blocks" [[ + (* TODO expression *) in + ]] in + do* M.assign "recent_canonical_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition pay_rewards (state : State) (block_number : Uint) (coinbase : Address) (ommers : (* TODO type *)) : M unit := + (* + 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. + *) + do* M.assign "ommer_count" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + ommers + |) + |) in + ]] in + do* M.assign "miner_reward" [[ + (* TODO expression *) in + ]] in + do* [[ state.create_ether ~(| + state, + coinbase, + M.get_local ~(| "miner_reward" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + do* M.assign "gas_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_pre155 (tx : Transaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_155 (tx : Transaction) (chain_id : U64) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_block_difficulty (block_number : Uint) (block_timestamp : U256) (parent_timestamp : U256) (parent_difficulty : Uint) (parent_has_ommers : bool) : M Uint := + (* + 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. + *) + do* M.assign "offset" [[ + (* TODO expression *) in + ]] in + do* M.assign "difficulty" [[ + (* TODO expression *) in + ]] in + do* M.assign "num_bomb_periods" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/fork_types.ast b/coq/ethereum/istanbul/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/istanbul/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/fork_types.v b/coq/ethereum/istanbul/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/istanbul/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/state.ast b/coq/ethereum/istanbul/state.ast new file mode 100644 index 0000000000..c04909fdce --- /dev/null +++ b/coq/ethereum/istanbul/state.ast @@ -0,0 +1,1692 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='created_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='set', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mark_account_created', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Mark an account as having been created in the current transaction.\n This information is used by `get_storage_original()` to handle an obscure\n edgecase.\n\n The marker is not removed even if the account creation reverts. Since the\n account cannot have had code prior to its creation and can't call\n `get_storage_original()`, this is harmless.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account that has been created.\n ")), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has zero nonce, empty code and zero balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_empty : `bool`\n True if if an account has zero nonce, empty code and zero balance,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_exists_and_is_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists and has zero nonce, empty code and zero\n balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n exists_and_is_empty : `bool`\n True if an account exists and has zero nonce, empty code and zero\n balance, False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='account', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_alive', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether is an account is both in the state and non empty.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_alive : `bool`\n True if the account is alive.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[ + Return( + value=UnaryOp( + op=Not(), + operand=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])])))])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add newly created ether to an account.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to which ether is added.\n amount:\n The amount of ether to be added to the account of interest.\n ')), + FunctionDef( + name='increase_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage_original', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the original value in a storage slot i.e. the value before the current\n transaction began. This function reads the value from the snapshots taken\n before executing the transaction.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to read the value from.\n key:\n Key of the storage slot.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='_', ctx=Store()), + Name(id='original_trie', ctx=Store())], + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + Assign( + targets=[ + Name(id='original_account_trie', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='original_trie', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='original_account_trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='original_account_trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[]))]), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='original_value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='original_value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/state.v b/coq/ethereum/istanbul/state.v new file mode 100644 index 0000000000..ba5f792df9 --- /dev/null +++ b/coq/ethereum/istanbul/state.v @@ -0,0 +1,614 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.istanbul.fork_types. +Require ethereum.istanbul.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition mark_account_created (state : State) (address : Address) : M unit := + (* + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| + address + |) ]] in + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_empty (state : State) (address : Address) : M bool := + (* + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition account_exists_and_is_empty (state : State) (address : Address) : M bool := + (* + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_alive (state : State) (address : Address) : M bool := + (* + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := + (* + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. + +Definition get_storage_original (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + *) + (* TODO statement *) + (* TODO assignment *) + do* M.assign "original_account_trie" [[ + M.get_field ~(| M.get_local ~(| "original_trie" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/transactions.ast b/coq/ethereum/istanbul/transactions.ast new file mode 100644 index 0000000000..466c329804 --- /dev/null +++ b/coq/ethereum/istanbul/transactions.ast @@ -0,0 +1,106 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + ClassDef( + name='Transaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/transactions.v b/coq/ethereum/istanbul/transactions.v new file mode 100644 index 0000000000..dccbd94f85 --- /dev/null +++ b/coq/ethereum/istanbul/transactions.v @@ -0,0 +1,13 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.istanbul.fork_types. diff --git a/coq/ethereum/istanbul/trie.ast b/coq/ethereum/istanbul/trie.ast new file mode 100644 index 0000000000..54213af8ae --- /dev/null +++ b/coq/ethereum/istanbul/trie.ast @@ -0,0 +1,1618 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.constantinople', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.RLP`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/trie.v b/coq/ethereum/istanbul/trie.v new file mode 100644 index 0000000000..6b8953f256 --- /dev/null +++ b/coq/ethereum/istanbul/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/utils/__init__.ast b/coq/ethereum/istanbul/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/istanbul/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/utils/__init__.v b/coq/ethereum/istanbul/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/istanbul/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/istanbul/utils/address.ast b/coq/ethereum/istanbul/utils/address.ast new file mode 100644 index 0000000000..4958c556dd --- /dev/null +++ b/coq/ethereum/istanbul/utils/address.ast @@ -0,0 +1,216 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this istanbul version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_create2_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='salt', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='call_data', + annotation=Name(id='bytearray', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created, which is\n based on the sender address, salt and the call data as well.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n salt :\n Address generation salt.\n call_data :\n The code of the new account which is to be created.\n\n Returns\n -------\n address: `ethereum.istanbul.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='preimage', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Constant(value=b'\xff'), + op=Add(), + right=Name(id='address', ctx=Load())), + op=Add(), + right=Name(id='salt', ctx=Load())), + op=Add(), + right=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='call_data', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/utils/address.v b/coq/ethereum/istanbul/utils/address.v new file mode 100644 index 0000000000..218a3bbba0 --- /dev/null +++ b/coq/ethereum/istanbul/utils/address.v @@ -0,0 +1,115 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this istanbul version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.istanbul.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition compute_create2_contract_address (address : Address) (salt : Bytes32) (call_data : bytearray) : M Address := + (* + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.istanbul.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "preimage" [[ + (* TODO expression *) in + ]] in + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "preimage" |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/utils/hexadecimal.ast b/coq/ethereum/istanbul/utils/hexadecimal.ast new file mode 100644 index 0000000000..faf2e4c459 --- /dev/null +++ b/coq/ethereum/istanbul/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to\nIstanbul types.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/utils/hexadecimal.v b/coq/ethereum/istanbul/utils/hexadecimal.v new file mode 100644 index 0000000000..7cc192c3ba --- /dev/null +++ b/coq/ethereum/istanbul/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Istanbul types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.istanbul.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/utils/message.ast b/coq/ethereum/istanbul/utils/message.ast new file mode 100644 index 0000000000..3a23f2dec3 --- /dev/null +++ b/coq/ethereum/istanbul/utils/message.ast @@ -0,0 +1,241 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this istanbul version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_static', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True), + Constant(value=False)]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n is_static:\n if True then it prevents all state-changing operations from being\n executed.\n\n Returns\n -------\n message: `ethereum.istanbul.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=Name(id='is_static', ctx=Load())), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/utils/message.v b/coq/ethereum/istanbul/utils/message.v new file mode 100644 index 0000000000..58d70c6adc --- /dev/null +++ b/coq/ethereum/istanbul/utils/message.v @@ -0,0 +1,60 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this istanbul version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.istanbul.fork_types. +Require ethereum.istanbul.state. +Require ethereum.istanbul.vm. +Require ethereum.istanbul.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) (is_static : bool) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + + Returns + ------- + message: `ethereum.istanbul.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/__init__.ast b/coq/ethereum/istanbul/vm/__init__.ast new file mode 100644 index 0000000000..d2a1a3d8d7 --- /dev/null +++ b/coq/ethereum/istanbul/vm/__init__.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty')], + level=2), + ImportFrom( + module='precompiled_contracts', + names=[ + alias(name='RIPEMD160_ADDRESS')], + level=1), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='is_static', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='return_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + If( + test=Compare( + left=Name(id='RIPEMD160_ADDRESS', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/__init__.v b/coq/ethereum/istanbul/vm/__init__.v new file mode 100644 index 0000000000..ee3f398c83 --- /dev/null +++ b/coq/ethereum/istanbul/vm/__init__.v @@ -0,0 +1,72 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.istanbul.blocks. +Require ethereum.istanbul.fork_types. +Require ethereum.istanbul.state. +Require ethereum.istanbul.vm.precompiled_contracts. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "touched_accounts" |), "update" |) ~(| + M.get_field ~(| child_evm, "touched_accounts" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + (* TODO statement *) + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/exceptions.ast b/coq/ethereum/istanbul/vm/exceptions.ast new file mode 100644 index 0000000000..1a05416bbd --- /dev/null +++ b/coq/ethereum/istanbul/vm/exceptions.ast @@ -0,0 +1,165 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='Revert', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised by the `REVERT` opcode.\n\n Unlike other EVM exceptions this does not result in the consumption of all\n gas.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='WriteInStaticContext', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt is made to modify the state while operating inside\n of a STATICCALL context.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfBoundsRead', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt was made to read data beyond the\n boundaries of the buffer.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidParameter', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when invalid parameters are passed.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/exceptions.v b/coq/ethereum/istanbul/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/istanbul/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/istanbul/vm/gas.ast b/coq/ethereum/istanbul/vm/gas.ast new file mode 100644 index 0000000000..3268524e5e --- /dev/null +++ b/coq/ethereum/istanbul/vm/gas.ast @@ -0,0 +1,833 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=800)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXTERNAL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BALANCE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='REFUND_SELF_DESTRUCT', ctx=Store())], + value=Constant(value=24000)), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RETURN_DATA_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_FAST_STEP', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLAKE2_PER_ROUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_left', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='memory_cost', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='extra_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='call_stipend', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Expr( + value=Constant(value='\n Calculates the MessageCallGas (cost and stipend) for\n executing call Opcodes.\n\n Parameters\n ----------\n value:\n The amount of `ETH` that needs to be transferred.\n gas :\n The amount of gas provided to the message-call.\n gas_left :\n The amount of gas left in the current frame.\n memory_cost :\n The amount needed to extend the memory in the current frame.\n extra_gas :\n The amount of gas needed for transferring value + creating a new\n account inside a message call.\n call_stipend :\n The amount of stipend provided to a message call to execute code while\n transferring value(ETH).\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='call_stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='call_stipend', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='extra_gas', ctx=Load()), + op=Add(), + right=Name(id='memory_cost', ctx=Load()))]), + body=[ + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='gas', ctx=Load()), + Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='gas_left', ctx=Load()), + op=Sub(), + right=Name(id='memory_cost', ctx=Load())), + op=Sub(), + right=Name(id='extra_gas', ctx=Load()))], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load())), + FunctionDef( + name='max_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the maximum gas that is allowed for making a message call\n\n Parameters\n ----------\n gas :\n The amount of gas provided to the message-call.\n\n Returns\n -------\n max_allowed_message_call_gas: `ethereum.base_types.Uint`\n The maximum gas allowed for making the message-call.\n ')), + Return( + value=BinOp( + left=Name(id='gas', ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='gas', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]))))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/gas.v b/coq/ethereum/istanbul/vm/gas.v new file mode 100644 index 0000000000..c7bbce3e4a --- /dev/null +++ b/coq/ethereum/istanbul/vm/gas.v @@ -0,0 +1,171 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (value : U256) (gas : Uint) (gas_left : Uint) (memory_cost : Uint) (extra_gas : Uint) (call_stipend : Uint) : M MessageCallGas := + (* + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "gas" [[ + M.get_local ~(| "min" |) ~(| + gas, + M.get_local ~(| "max_message_call_gas" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition max_message_call_gas (gas : Uint) : M Uint := + (* + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/instructions/__init__.ast b/coq/ethereum/istanbul/vm/instructions/__init__.ast new file mode 100644 index 0000000000..4f4c60bb9b --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/__init__.ast @@ -0,0 +1,1780 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='SHL', ctx=Store())], + value=Constant(value=27)), + Assign( + targets=[ + Name(id='SHR', ctx=Store())], + value=Constant(value=28)), + Assign( + targets=[ + Name(id='SAR', ctx=Store())], + value=Constant(value=29)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='RETURNDATASIZE', ctx=Store())], + value=Constant(value=61)), + Assign( + targets=[ + Name(id='RETURNDATACOPY', ctx=Store())], + value=Constant(value=62)), + Assign( + targets=[ + Name(id='EXTCODEHASH', ctx=Store())], + value=Constant(value=63)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='DIFFICULTY', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='CHAINID', ctx=Store())], + value=Constant(value=70)), + Assign( + targets=[ + Name(id='SELFBALANCE', ctx=Store())], + value=Constant(value=71)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='CREATE2', ctx=Store())], + value=Constant(value=245)), + Assign( + targets=[ + Name(id='STATICCALL', ctx=Store())], + value=Constant(value=250)), + Assign( + targets=[ + Name(id='REVERT', ctx=Store())], + value=Constant(value=253)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SAR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIFFICULTY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CHAINID', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODEHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFBALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STATICCALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='REVERT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE2', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shl', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shr', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_sar', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodehash', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='self_balance', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='staticcall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='revert', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create2', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/instructions/__init__.v b/coq/ethereum/istanbul/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/istanbul/vm/instructions/arithmetic.ast b/coq/ethereum/istanbul/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/instructions/arithmetic.v b/coq/ethereum/istanbul/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..b887ac7471 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/instructions/bitwise.ast b/coq/ethereum/istanbul/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..b72397f0ec --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/bitwise.ast @@ -0,0 +1,751 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shl', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift left (SHL) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='value', ctx=Load()), + op=LShift(), + right=Name(id='shift', ctx=Load())), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]))], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shr', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift right (SHR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_sar', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Arithmetic shift right (SAR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='signed_value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=256)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + BinOp( + left=Name(id='signed_value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load()))], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='signed_value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load()))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/instructions/bitwise.v b/coq/ethereum/istanbul/vm/instructions/bitwise.v new file mode 100644 index 0000000000..579f9bffee --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/bitwise.v @@ -0,0 +1,309 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shl (evm : Evm) : M unit := + (* + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shr (evm : Evm) : M unit := + (* + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_sar (evm : Evm) : M unit := + (* + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + M.get_local ~(| "int" |) ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "signed_value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/instructions/block.ast b/coq/ethereum/istanbul/vm/instructions/block.ast new file mode 100644 index 0000000000..b9ccb3290b --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/block.ast @@ -0,0 +1,492 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's difficulty onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='chain_id', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the chain id onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/instructions/block.v b/coq/ethereum/istanbul/vm/instructions/block.v new file mode 100644 index 0000000000..6d34d6ab14 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/block.v @@ -0,0 +1,241 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition difficulty (evm : Evm) : M unit := + (* + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition chain_id (evm : Evm) : M unit := + (* + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/instructions/comparison.ast b/coq/ethereum/istanbul/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/instructions/comparison.v b/coq/ethereum/istanbul/vm/instructions/comparison.v new file mode 100644 index 0000000000..ce8667aab5 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/instructions/control_flow.ast b/coq/ethereum/istanbul/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/instructions/control_flow.v b/coq/ethereum/istanbul/vm/instructions/control_flow.v new file mode 100644 index 0000000000..4c5791a1ee --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.exceptions. +Require ethereum.istanbul.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/instructions/environment.ast b/coq/ethereum/istanbul/vm/instructions/environment.ast new file mode 100644 index 0000000000..859f5acfff --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/environment.ast @@ -0,0 +1,1641 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfBoundsRead')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BALANCE'), + alias(name='GAS_BASE'), + alias(name='GAS_CODE_HASH'), + alias(name='GAS_COPY'), + alias(name='GAS_EXTERNAL'), + alias(name='GAS_FAST_STEP'), + alias(name='GAS_RETURN_DATA_COPY'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BALANCE', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_EXTERNAL', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_EXTERNAL', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the size of the return data buffer onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copies data from the return data buffer code to memory\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='return_data_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_RETURN_DATA_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='return_data_start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfBoundsRead', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load()), + slice=Slice( + lower=Name(id='return_data_start_position', ctx=Load()), + upper=BinOp( + left=Name(id='return_data_start_position', ctx=Load()), + op=Add(), + right=Name(id='size', ctx=Load()))), + ctx=Load())), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodehash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns the keccak256 hash of a contract’s bytecode\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_CODE_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='EMPTY_ACCOUNT', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codehash', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='self_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the current address to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_FAST_STEP', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/instructions/environment.v b/coq/ethereum/istanbul/vm/instructions/environment.v new file mode 100644 index 0000000000..a051868a52 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/environment.v @@ -0,0 +1,712 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.istanbul.fork_types. +Require ethereum.istanbul.state. +Require ethereum.istanbul.utils.address. +Require ethereum.istanbul.vm.memory. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.exceptions. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BALANCE + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_EXTERNAL + |) ]] in + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatasize (evm : Evm) : M unit := + (* + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatacopy (evm : Evm) : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "return_data_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + (* TODO expression *) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodehash (evm : Evm) : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_CODE_HASH + |) ]] in + do* M.assign "account" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codehash" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition self_balance (evm : Evm) : M unit := + (* + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_FAST_STEP + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/instructions/keccak.ast b/coq/ethereum/istanbul/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/instructions/keccak.v b/coq/ethereum/istanbul/vm/instructions/keccak.v new file mode 100644 index 0000000000..49f1dcc927 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.memory. +Require ethereum.istanbul.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/instructions/log.ast b/coq/ethereum/istanbul/vm/instructions/log.ast new file mode 100644 index 0000000000..0ded0e04ba --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/log.ast @@ -0,0 +1,323 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/instructions/log.v b/coq/ethereum/istanbul/vm/instructions/log.v new file mode 100644 index 0000000000..f57792524a --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/log.v @@ -0,0 +1,79 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.istanbul.blocks. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.exceptions. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.memory. +Require ethereum.istanbul.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO statement *) + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/instructions/memory.ast b/coq/ethereum/istanbul/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/instructions/memory.v b/coq/ethereum/istanbul/vm/instructions/memory.v new file mode 100644 index 0000000000..5a8020e554 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.memory. +Require ethereum.istanbul.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/instructions/stack.ast b/coq/ethereum/istanbul/vm/instructions/stack.ast new file mode 100644 index 0000000000..95cfc0b6cf --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/stack.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/instructions/stack.v b/coq/ethereum/istanbul/vm/instructions/stack.v new file mode 100644 index 0000000000..656d6fb2e3 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/stack.v @@ -0,0 +1,153 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.exceptions. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/instructions/storage.ast b/coq/ethereum/istanbul/vm/instructions/storage.ast new file mode 100644 index 0000000000..1930ab7b69 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/storage.ast @@ -0,0 +1,437 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='get_storage_original'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_STIPEND'), + alias(name='GAS_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_SLOAD', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='get_storage_original', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='current_value', ctx=Load())]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())])]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_UPDATE', ctx=Load()))])], + orelse=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SLOAD', ctx=Load()))]), + If( + test=Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='GAS_STORAGE_SET', ctx=Load()), + op=Sub(), + right=Name(id='GAS_SLOAD', ctx=Load()))], + keywords=[]))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_SLOAD', ctx=Load()))], + keywords=[]))])], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/instructions/storage.v b/coq/ethereum/istanbul/vm/instructions/storage.v new file mode 100644 index 0000000000..5776260122 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/storage.v @@ -0,0 +1,118 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.istanbul.state. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.exceptions. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_SLOAD + |) ]] in + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "original_value" [[ + state.get_storage_original ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/instructions/system.ast b/coq/ethereum/istanbul/vm/instructions/system.ast new file mode 100644 index 0000000000..6801ce9810 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/system.ast @@ -0,0 +1,2745 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='is_account_alive'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='compute_create2_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='Revert'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL'), + alias(name='GAS_CALL_VALUE'), + alias(name='GAS_CREATE'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='GAS_NEW_ACCOUNT'), + alias(name='GAS_SELF_DESTRUCT'), + alias(name='GAS_SELF_DESTRUCT_NEW_ACCOUNT'), + alias(name='GAS_ZERO'), + alias(name='REFUND_SELF_DESTRUCT'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas'), + alias(name='max_message_call_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='generic_create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='endowment', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='contract_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='memory_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Core logic used by the `CREATE*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='create_message_gas', ctx=Load())), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='is_static', + value=Constant(value=False)), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create2', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Creates a new account with associated code.\n\n It's similar to CREATE opcode except that the address of new account\n depends on the init_code instead of the nonce of sender.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ")), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='salt', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='call_data_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='call_data_words', ctx=Load()))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_create2_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='salt', ctx=Load()), + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_staticcall', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=IfExp( + test=Name(id='is_staticcall', ctx=Load()), + body=Constant(value=True), + orelse=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()))), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[])]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SELF_DESTRUCT', ctx=Load())), + If( + test=BoolOp( + op=And(), + values=[ + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[])), + Compare( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='refunded_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load())), + While( + test=Compare( + left=Name(id='parent_evm', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='refunded_accounts', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='originator', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='refunded_accounts', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Name(id='REFUND_SELF_DESTRUCT', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='GAS_CALL', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='staticcall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='GAS_CALL', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='revert', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop execution and revert state changes, without consuming all provided gas\n and also has the ability to return a reason\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Name(id='output', ctx=Load())], + keywords=[])), + Raise( + exc=Name(id='Revert', ctx=Load())), + Pass()], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/instructions/system.v b/coq/ethereum/istanbul/vm/instructions/system.v new file mode 100644 index 0000000000..ff5f1bf015 --- /dev/null +++ b/coq/ethereum/istanbul/vm/instructions/system.v @@ -0,0 +1,779 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.istanbul.fork_types. +Require ethereum.istanbul.state. +Require ethereum.istanbul.utils.address. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.exceptions. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.memory. +Require ethereum.istanbul.vm.stack. + +Definition generic_create (evm : Evm) (endowment : U256) (contract_address : Address) (memory_start_position : U256) (memory_size : U256) : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* M.assign "create_message_gas" [[ + gas.max_message_call_gas ~(| + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) in + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_local ~(| "create_message_gas" |) + ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_start_position, + memory_size + |) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_create_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition create2 (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "salt" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "call_data_words" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_create2_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "salt" |), + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (is_staticcall : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_SELF_DESTRUCT in + ]] in + (* TODO statement *) + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "refunded_accounts" [[ + M.get_field ~(| evm, "accounts_to_delete" |) in + ]] in + do* M.assign "parent_evm" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "parent_evm" |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + gas.GAS_CALL + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition staticcall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + gas.GAS_CALL + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "to" |), + M.get_local ~(| "to" |), + True, + True, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition revert (evm : Evm) : M unit := + (* + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "output" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/interpreter.ast b/coq/ethereum/istanbul/vm/interpreter.ast new file mode 100644 index 0000000000..73c1cdc9cb --- /dev/null +++ b/coq/ethereum/istanbul/vm/interpreter.ast @@ -0,0 +1,1137 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Iterable'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='increment_nonce'), + alias(name='mark_account_created'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidOpcode'), + alias(name='OutOfGasError'), + alias(name='Revert'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_CODE_SIZE', ctx=Store())], + value=Constant(value=24576)), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `touched_accounts`: Accounts that have been touched.\n 6. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='touched_accounts', + value=Name(id='touched_accounts', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.istanbul.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='mark_account_created', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_CODE_SIZE', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.istanbul.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='touched_accounts', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='return_data', + value=Constant(value=b'')), + keyword( + arg='error', + value=Constant(value=None))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))]), + ExceptHandler( + type=Name(id='Revert', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/interpreter.v b/coq/ethereum/istanbul/vm/interpreter.v new file mode 100644 index 0000000000..00b0112fcb --- /dev/null +++ b/coq/ethereum/istanbul/vm/interpreter.v @@ -0,0 +1,173 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.istanbul.blocks. +Require ethereum.istanbul.fork_types. +Require ethereum.istanbul.state. +Require ethereum.istanbul.vm. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.precompiled_contracts.mapping. +Require ethereum.istanbul.vm.__init__. +Require ethereum.istanbul.vm.exceptions. +Require ethereum.istanbul.vm.instructions. +Require ethereum.istanbul.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.istanbul.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.mark_account_created ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.istanbul.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/memory.ast b/coq/ethereum/istanbul/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/istanbul/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/memory.v b/coq/ethereum/istanbul/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/istanbul/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/__init__.ast b/coq/ethereum/istanbul/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..bb9991907f --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS'), + Constant(value='MODEXP_ADDRESS'), + Constant(value='ALT_BN128_ADD_ADDRESS'), + Constant(value='ALT_BN128_MUL_ADDRESS'), + Constant(value='ALT_BN128_PAIRING_CHECK_ADDRESS'), + Constant(value='BLAKE2F_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[])), + Assign( + targets=[ + Name(id='MODEXP_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x05')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x06')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x07')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x08')], + keywords=[])), + Assign( + targets=[ + Name(id='BLAKE2F_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x09')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/__init__.v b/coq/ethereum/istanbul/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..dabf66a6c6 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.istanbul.utils.hexadecimal. diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.ast b/coq/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.ast new file mode 100644 index 0000000000..f6f077419c --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.ast @@ -0,0 +1,913 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ALT_BN128 CONTRACTS\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ALT_BN128 precompiled contracts.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.alt_bn128', + names=[ + alias(name='ALT_BN128_CURVE_ORDER'), + alias(name='ALT_BN128_PRIME'), + alias(name='BNF'), + alias(name='BNF2'), + alias(name='BNF12'), + alias(name='BNP'), + alias(name='BNP2'), + alias(name='pairing')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=2), + FunctionDef( + name='alt_bn128_add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 addition precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=150)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load()), + Name(id='x1_value', ctx=Load()), + Name(id='y1_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='p1', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x1_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y1_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=BinOp( + left=Name(id='p0', ctx=Load()), + op=Add(), + right=Name(id='p1', ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 multiplication precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6000)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='n', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='p0', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='n', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_pairing_check', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 pairing check precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=34000), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))), + op=Add(), + right=Constant(value=45000))], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=192)), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='values', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=Name(id='j', ctx=Load()))), + upper=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=BinOp( + left=Name(id='j', ctx=Load()), + op=Add(), + right=Constant(value=1))))), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='values', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=Call( + func=Name(id='BNP2', ctx=Load()), + args=[ + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=3), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=2), + ctx=Load())], + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=5), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=4), + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='OutOfGasError', ctx=Load()), + args=[], + keywords=[]))])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='p', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='q', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='p', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + Compare( + left=Name(id='q', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='result', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='pairing', ctx=Load()), + args=[ + Name(id='q', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[])))], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='result', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000000..421c8dbcc2 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,226 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.alt_bn128. +Require ethereum.istanbul.vm. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.memory. +Require ethereum.istanbul.vm.exceptions. + +Definition alt_bn128_add (evm : Evm) : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 150 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "x1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x1_bytes" |) + |) + |) in + ]] in + do* M.assign "y1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y1_bytes" |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + (* TODO expression *) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_mul (evm : Evm) : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 6000 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "n" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + M.get_field ~(| M.get_local ~(| "p0" |), "mul_by" |) ~(| + M.get_local ~(| "n" |) + |) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_pairing_check (evm : Evm) : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + (* TODO expression *) + |) + |) ]] in + (* TODO statement *) + do* M.assign "result" [[ + M.get_field ~(| ethereum.crypto.alt_bn128.BNF12, "from_int" |) ~(| + 1 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/blake2f.ast b/coq/ethereum/istanbul/vm/precompiled_contracts/blake2f.ast new file mode 100644 index 0000000000..03747962f0 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/blake2f.ast @@ -0,0 +1,137 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `Blake2` precompiled contract.\n')), + ImportFrom( + module='ethereum.crypto.blake2', + names=[ + alias(name='Blake2b')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BLAKE2_PER_ROUND'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidParameter')], + level=2), + FunctionDef( + name='blake2f', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the Blake2 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Constant(value=213)]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='blake2b', ctx=Store())], + value=Call( + func=Name(id='Blake2b', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='rounds', ctx=Store()), + Name(id='h', ctx=Store()), + Name(id='m', ctx=Store()), + Name(id='t_0', ctx=Store()), + Name(id='t_1', ctx=Store()), + Name(id='f', ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='get_blake2_parameters', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_BLAKE2_PER_ROUND', ctx=Load()), + op=Mult(), + right=Name(id='rounds', ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=Name(id='f', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + List( + elts=[ + Constant(value=0), + Constant(value=1)], + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='compress', + ctx=Load()), + args=[ + Name(id='rounds', ctx=Load()), + Name(id='h', ctx=Load()), + Name(id='m', ctx=Load()), + Name(id='t_0', ctx=Load()), + Name(id='t_1', ctx=Load()), + Name(id='f', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/blake2f.v b/coq/ethereum/istanbul/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000000..57bdca10e9 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,46 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +*) + +Require ethereum.crypto.blake2. +Require ethereum.istanbul.vm. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.exceptions. + +Definition blake2f (evm : Evm) : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + (* TODO statement *) + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| + + |) in + ]] in + (* TODO assignment *) + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/istanbul/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/istanbul/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..f0e9bb8dd1 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.istanbul.vm. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/identity.ast b/coq/ethereum/istanbul/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/identity.v b/coq/ethereum/istanbul/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..bf550e5050 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.istanbul.vm. +Require ethereum.istanbul.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/mapping.ast b/coq/ethereum/istanbul/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..cec40e5736 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ALT_BN128_ADD_ADDRESS'), + alias(name='ALT_BN128_MUL_ADDRESS'), + alias(name='ALT_BN128_PAIRING_CHECK_ADDRESS'), + alias(name='BLAKE2F_ADDRESS'), + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='MODEXP_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='alt_bn128', + names=[ + alias(name='alt_bn128_add'), + alias(name='alt_bn128_mul'), + alias(name='alt_bn128_pairing_check')], + level=1), + ImportFrom( + module='blake2f', + names=[ + alias(name='blake2f')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='modexp', + names=[ + alias(name='modexp')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load()), + Name(id='MODEXP_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Load()), + Name(id='BLAKE2F_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load()), + Name(id='modexp', ctx=Load()), + Name(id='alt_bn128_add', ctx=Load()), + Name(id='alt_bn128_mul', ctx=Load()), + Name(id='alt_bn128_pairing_check', ctx=Load()), + Name(id='blake2f', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/mapping.v b/coq/ethereum/istanbul/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..6ec0c37466 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/mapping.v @@ -0,0 +1,25 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.istanbul.fork_types. +Require ethereum.istanbul.vm.precompiled_contracts.__init__. +Require ethereum.istanbul.vm.precompiled_contracts.alt_bn128. +Require ethereum.istanbul.vm.precompiled_contracts.blake2f. +Require ethereum.istanbul.vm.precompiled_contracts.ecrecover. +Require ethereum.istanbul.vm.precompiled_contracts.identity. +Require ethereum.istanbul.vm.precompiled_contracts.modexp. +Require ethereum.istanbul.vm.precompiled_contracts.ripemd160. +Require ethereum.istanbul.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/modexp.ast b/coq/ethereum/istanbul/vm/precompiled_contracts/modexp.ast new file mode 100644 index 0000000000..010c07fd00 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/modexp.ast @@ -0,0 +1,631 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `MODEXP` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + Assign( + targets=[ + Name(id='GQUADDIVISOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + FunctionDef( + name='modexp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and.\n `modulus`. The return value is the same length as the modulus.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='base_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_start', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Add(), + right=Name(id='base_length', ctx=Load()))), + Assign( + targets=[ + Name(id='exp_head', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Call( + func=Name(id='min', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='gas_cost', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load()), + Name(id='exp_length', ctx=Load()), + Name(id='exp_head', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='base_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='modulus_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Name(id='base_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_start', ctx=Store())], + value=BinOp( + left=Name(id='exp_start', ctx=Load()), + op=Add(), + right=Name(id='exp_length', ctx=Load()))), + Assign( + targets=[ + Name(id='modulus', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='modulus_start', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='modulus', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'\x00')], + keywords=[]), + op=Mult(), + right=Name(id='modulus_length', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exp', ctx=Load()), + Name(id='modulus', ctx=Load())], + keywords=[]), + attr='to_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[]), + Constant(value='big')], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='complexity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Estimate the complexity of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n Returns\n -------\n\n complexity : `Uint`\n Complexity of performing the operation.\n ')), + Assign( + targets=[ + Name(id='max_length', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load())], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='max_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[])]), + body=[ + Return( + value=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='max_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])]), + body=[ + Return( + value=BinOp( + left=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=4)], + keywords=[])), + op=Add(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Mult(), + right=Name(id='max_length', ctx=Load()))), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3072)], + keywords=[])))], + orelse=[ + Return( + value=BinOp( + left=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[])), + op=Add(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=480)], + keywords=[]), + op=Mult(), + right=Name(id='max_length', ctx=Load()))), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=199680)], + keywords=[])))])])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='iterations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the number of iterations required to perform a modular\n exponentiation.\n\n Parameters\n ----------\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n iterations : `Uint`\n Number of iterations.\n ')), + If( + test=Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='adjusted_exp_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Constant(value=0), + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + op=Sub(), + right=Constant(value=1))], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='adjusted_exp_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=8), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=32))), + op=Add(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + Constant(value=0), + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + op=Sub(), + right=Constant(value=1))], + keywords=[]))], + keywords=[]))]), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='adjusted_exp_length', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the gas cost of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n gas_cost : `Uint`\n Gas required for performing the operation.\n ')), + Assign( + targets=[ + Name(id='multiplication_complexity', ctx=Store())], + value=Call( + func=Name(id='complexity', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='iteration_count', ctx=Store())], + value=Call( + func=Name(id='iterations', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load()), + Name(id='exponent_head', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cost', ctx=Store())], + value=BinOp( + left=Name(id='multiplication_complexity', ctx=Load()), + op=Mult(), + right=Name(id='iteration_count', ctx=Load()))), + AugAssign( + target=Name(id='cost', ctx=Store()), + op=FloorDiv(), + value=Name(id='GQUADDIVISOR', ctx=Load())), + Return( + value=Name(id='cost', ctx=Load()))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/modexp.v b/coq/ethereum/istanbul/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000000..8fa919e8bb --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/modexp.v @@ -0,0 +1,233 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.istanbul.vm. +Require ethereum.istanbul.vm.gas. +Require ethereum.istanbul.vm.memory. + +Definition modexp (evm : Evm) : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "base_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "modulus_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "exp_head" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "min" |) ~(| + ethereum_types.numeric.U256 ~(| + 32 + |), + M.get_local ~(| "exp_length" |) + |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) ~(| + M.get_local ~(| "base_length" |), + M.get_local ~(| "modulus_length" |), + M.get_local ~(| "exp_length" |), + M.get_local ~(| "exp_head" |) + |) + |) ]] in + (* TODO statement *) + do* M.assign "base" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + M.get_local ~(| "base_length" |) + |) + |) in + ]] in + do* M.assign "exp" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "exp_length" |) + |) + |) in + ]] in + do* M.assign "modulus_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "modulus" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "modulus_start" |), + M.get_local ~(| "modulus_length" |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := + (* + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + *) + do* M.assign "max_length" [[ + M.get_local ~(| "max" |) ~(| + ethereum_types.numeric.Uint ~(| + base_length + |), + ethereum_types.numeric.Uint ~(| + modulus_length + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition gas_cost (base_length : U256) (modulus_length : U256) (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + *) + do* M.assign "multiplication_complexity" [[ + M.get_local ~(| "complexity" |) ~(| + base_length, + modulus_length + |) in + ]] in + do* M.assign "iteration_count" [[ + M.get_local ~(| "iterations" |) ~(| + exponent_length, + exponent_head + |) in + ]] in + do* M.assign "cost" [[ + (* TODO expression *) in + ]] in + do* M.aug_assign [[ M.get_local ~(| "cost" |) ]] [[ + M.get_local ~(| "GQUADDIVISOR" |) + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/istanbul/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/istanbul/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/sha256.ast b/coq/ethereum/istanbul/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/precompiled_contracts/sha256.v b/coq/ethereum/istanbul/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/istanbul/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/runtime.ast b/coq/ethereum/istanbul/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/istanbul/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/runtime.v b/coq/ethereum/istanbul/vm/runtime.v new file mode 100644 index 0000000000..caedf31bb2 --- /dev/null +++ b/coq/ethereum/istanbul/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.istanbul.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/istanbul/vm/stack.ast b/coq/ethereum/istanbul/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/istanbul/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/istanbul/vm/stack.v b/coq/ethereum/istanbul/vm/stack.v new file mode 100644 index 0000000000..513ccc7d9e --- /dev/null +++ b/coq/ethereum/istanbul/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.istanbul.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/__init__.ast b/coq/ethereum/london/__init__.ast new file mode 100644 index 0000000000..54e1f83827 --- /dev/null +++ b/coq/ethereum/london/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe London fork overhauls the transaction fee market, changes gas refunds,\nreserves a contract prefix for future use, and delays the difficulty bomb.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=12965000)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/__init__.v b/coq/ethereum/london/__init__.v new file mode 100644 index 0000000000..1837593c36 --- /dev/null +++ b/coq/ethereum/london/__init__.v @@ -0,0 +1,7 @@ +(* Generated *) +(* +The London fork overhauls the transaction fee market, changes gas refunds, +reserves a contract prefix for future use, and delays the difficulty bomb. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/london/blocks.ast b/coq/ethereum/london/blocks.ast new file mode 100644 index 0000000000..06837ea5d6 --- /dev/null +++ b/coq/ethereum/london/blocks.ast @@ -0,0 +1,230 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='LegacyTransaction')], + level=1), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mix_digest', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='succeeded', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/blocks.v b/coq/ethereum/london/blocks.v new file mode 100644 index 0000000000..3ff6083ecb --- /dev/null +++ b/coq/ethereum/london/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.london.fork_types. +Require ethereum.london.transactions. diff --git a/coq/ethereum/london/bloom.ast b/coq/ethereum/london/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/london/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/bloom.v b/coq/ethereum/london/bloom.v new file mode 100644 index 0000000000..cac54af7e0 --- /dev/null +++ b/coq/ethereum/london/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.london.blocks. +Require ethereum.london.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/exceptions.ast b/coq/ethereum/london/exceptions.ast new file mode 100644 index 0000000000..a61ee25448 --- /dev/null +++ b/coq/ethereum/london/exceptions.ast @@ -0,0 +1,72 @@ +Module( + body=[ + Expr( + value=Constant(value='\nExceptions specific to this fork.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Final')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidTransaction')], + level=0), + ClassDef( + name='TransactionTypeError', + bases=[ + Name(id='InvalidTransaction', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Unknown [EIP-2718] transaction type byte.\n\n [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718\n ')), + AnnAssign( + target=Name(id='transaction_type', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n The type byte of the transaction that caused the error.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='transaction_type', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='unknown transaction type `'), + FormattedValue( + value=Name(id='transaction_type', ctx=Load()), + conversion=-1), + Constant(value='`')])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='transaction_type', + ctx=Store())], + value=Name(id='transaction_type', ctx=Load()))], + decorator_list=[])], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/exceptions.v b/coq/ethereum/london/exceptions.v new file mode 100644 index 0000000000..9a313f6d0e --- /dev/null +++ b/coq/ethereum/london/exceptions.v @@ -0,0 +1,7 @@ +(* Generated *) +(* +Exceptions specific to this fork. +*) + +Require typing. +Require ethereum.exceptions. diff --git a/coq/ethereum/london/fork.ast b/coq/ethereum/london/fork.ast new file mode 100644 index 0000000000..b7d9e99ca6 --- /dev/null +++ b/coq/ethereum/london/fork.ast @@ -0,0 +1,4019 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.ethash', + names=[ + alias(name='dataset_size'), + alias(name='generate_cache'), + alias(name='hashimoto_light')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='FORK_CRITERIA'), + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty'), + alias(name='create_ether'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_ACCESS_LIST_ADDRESS_COST'), + alias(name='TX_ACCESS_LIST_STORAGE_KEY_COST'), + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='AccessListTransaction'), + alias(name='FeeMarketTransaction'), + alias(name='LegacyTransaction'), + alias(name='Transaction'), + alias(name='decode_transaction'), + alias(name='encode_transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BLOCK_REWARD', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=18)))], + keywords=[])), + Assign( + targets=[ + Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='ELASTICITY_MULTIPLIER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=131072)], + keywords=[])), + Assign( + targets=[ + Name(id='INITIAL_BASE_FEE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1000000000)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_OMMER_DEPTH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='BOMB_DELAY_BLOCKS', ctx=Store())], + value=Constant(value=9700000)), + Assign( + targets=[ + Name(id='EMPTY_OMMER_HASH', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List(elts=[], ctx=Load())], + keywords=[])], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='validate_ommers', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='chain', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='chain', ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_base_fee_per_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the base fee per gas for the block.\n\n Parameters\n ----------\n block_gas_limit :\n Gas limit of the block for which the base fee is being calculated.\n parent_gas_limit :\n Gas limit of the parent block.\n parent_gas_used :\n Gas used in the parent block.\n parent_base_fee_per_gas :\n Base fee per gas of the parent block.\n\n Returns\n -------\n base_fee_per_gas : `Uint`\n Base fee per gas for the block.\n ')), + Assign( + targets=[ + Name(id='parent_gas_target', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='ELASTICITY_MULTIPLIER', ctx=Load()))), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Name(id='block_gas_limit', ctx=Load()), + Name(id='parent_gas_limit', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='parent_gas_used', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='parent_gas_target', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=Name(id='parent_base_fee_per_gas', ctx=Load()))], + orelse=[ + If( + test=Compare( + left=Name(id='parent_gas_used', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='parent_gas_target', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='gas_used_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_used', ctx=Load()), + op=Sub(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='parent_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Mult(), + right=Name(id='gas_used_delta', ctx=Load()))), + Assign( + targets=[ + Name(id='target_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='base_fee_per_gas_delta', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=Name(id='target_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Load())), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Add(), + right=Name(id='base_fee_per_gas_delta', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='gas_used_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_target', ctx=Load()), + op=Sub(), + right=Name(id='parent_gas_used', ctx=Load()))), + Assign( + targets=[ + Name(id='parent_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Mult(), + right=Name(id='gas_used_delta', ctx=Load()))), + Assign( + targets=[ + Name(id='target_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='base_fee_per_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='target_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Load()))), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Sub(), + right=Name(id='base_fee_per_gas_delta', ctx=Load())))])]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='expected_base_fee_per_gas', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=Name(id='INITIAL_BASE_FEE', ctx=Load())), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='FORK_CRITERIA', ctx=Load()), + attr='block_number', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_base_fee_per_gas', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='expected_base_fee_per_gas', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='parent_has_ommers', ctx=Store())], + value=Compare( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='EMPTY_OMMER_HASH', ctx=Load())])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_difficulty', ctx=Store())], + value=Call( + func=Name(id='calculate_block_difficulty', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Name(id='parent_has_ommers', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_difficulty', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='validate_proof_of_work', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generate_header_hash_for_pow', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate rlp hash of the header which is to be used for Proof-of-Work\n verification.\n\n In other words, the PoW artefacts `mix_digest` and `nonce` are ignored\n while calculating this hash.\n\n A particular PoW is valid for a single hash, that hash is computed by\n this function. The `nonce` and `mix_digest` are omitted from this hash\n because they are being changed by miners in their search for a sufficient\n proof-of-work.\n\n Parameters\n ----------\n header :\n The header object for which the hash is to be generated.\n\n Returns\n -------\n hash : `Hash32`\n The PoW valid rlp hash of the passed in header.\n ')), + Assign( + targets=[ + Name(id='header_data_without_pow_artefacts', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='state_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='transactions_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='receipt_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='bloom', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='header_data_without_pow_artefacts', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='validate_proof_of_work', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the Proof of Work constraints.\n\n In order to verify that a miner's proof-of-work is valid for a block, a\n ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``\n hash function. The mix digest is a hash of the header and the nonce that\n is passed through and it confirms whether or not proof-of-work was done\n on the correct block. The result is the actual hash value of the block.\n\n Parameters\n ----------\n header :\n Header of interest.\n ")), + Assign( + targets=[ + Name(id='header_hash', ctx=Store())], + value=Call( + func=Name(id='generate_header_hash_for_pow', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache', ctx=Store())], + value=Call( + func=Name(id='generate_cache', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='mix_digest', ctx=Store()), + Name(id='result', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='hashimoto_light', ctx=Load()), + args=[ + Name(id='header_hash', ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + Name(id='cache', ctx=Load()), + Call( + func=Name(id='dataset_size', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='mix_digest', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='mix_digest', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='limit', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='limit', ctx=Load()), + op=FloorDiv(), + right=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n base_fee_per_gas :\n The block base fee.\n gas_available :\n The gas remaining in the block.\n chain_id :\n The ID of the current chain.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n effective_gas_price :\n The price to charge for gas when the transaction is executed.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='base_fee_per_gas', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='priority_fee_per_gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + op=Sub(), + right=Name(id='base_fee_per_gas', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='effective_gas_price', ctx=Store())], + value=BinOp( + left=Name(id='priority_fee_per_gas', ctx=Load()), + op=Add(), + right=Name(id='base_fee_per_gas', ctx=Load())))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='base_fee_per_gas', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='effective_gas_price', ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))]), + Return( + value=Tuple( + elts=[ + Name(id='sender_address', ctx=Load()), + Name(id='effective_gas_price', ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='error', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n error :\n Error in the top level frame of the transaction, if any.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='succeeded', + value=Compare( + left=Name(id='error', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)])), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='receipt', ctx=Load())], + keywords=[])))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='receipt', ctx=Load())], + keywords=[])))], + orelse=[ + Return( + value=Name(id='receipt', ctx=Load()))])])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Receipt', ctx=Load())], + ctx=Load()), + ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='block_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n base_fee_per_gas :\n Base fee per gas of within the block.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n block_difficulty :\n Difficulty of the block.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Receipt', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Call( + func=Name(id='map', ctx=Load()), + args=[ + Name(id='decode_transaction', ctx=Load()), + Name(id='transactions', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Call( + func=Name(id='encode_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='sender_address', ctx=Store()), + Name(id='effective_gas_price', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='base_fee_per_gas', ctx=Load()), + Name(id='gas_available', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='base_fee_per_gas', + value=Name(id='base_fee_per_gas', ctx=Load())), + keyword( + arg='gas_price', + value=Name(id='effective_gas_price', ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='difficulty', + value=Name(id='block_difficulty', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='chain_id', + value=Name(id='chain_id', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store()), + Name(id='error', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='error', ctx=Load()), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='pay_rewards', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='block_number', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='ommers', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='validate_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='block_header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the ommers mentioned in the block.\n\n An ommer block is a block that wasn't canonically added to the\n blockchain because it wasn't validated as fast as the canonical block\n but was mined at the same time.\n\n To be considered valid, the ommers must adhere to the rules defined in\n the Ethereum protocol. The maximum amount of ommers is 2 per block and\n there cannot be duplicate ommers in a block. Many of the other ommer\n constraints are listed in the in-line comments of this function.\n\n Parameters\n ----------\n ommers :\n List of ommers mentioned in the current block.\n block_header:\n The header of current block.\n chain :\n History and current state.\n ")), + Assign( + targets=[ + Name(id='block_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='block_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='ommers_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return()], + orelse=[]), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + op=Sub(), + right=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Name(id='ommer', ctx=Load()), + Name(id='ommer_parent_header', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=2)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommers_hashes', ctx=Store())], + value=ListComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + ifs=[], + is_async=0)])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[])], + keywords=[])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_canonical_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=BinOp( + left=Name(id='MAX_OMMER_DEPTH', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + ctx=Load())), + Assign( + targets=[ + Name(id='recent_canonical_block_hashes', ctx=Store())], + value=SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='recent_ommers_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + simple=1), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='recent_ommers_hashes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='recent_ommers_hashes', ctx=Load()), + attr='union', + ctx=Load()), + args=[ + SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='ommer_index', ctx=Store()), + Name(id='ommer', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='ommer_hash', ctx=Store())], + value=Subscript( + value=Name(id='ommers_hashes', ctx=Load()), + slice=Name(id='ommer_index', ctx=Load()), + ctx=Load())), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='block_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_ommers_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='ommer_age', ctx=Load())]), + Compare( + left=Name(id='ommer_age', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_OMMER_DEPTH', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='parent_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pay_rewards', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pay rewards to the block miner as well as the ommers miners.\n\n The miner of the canonical block is rewarded with the predetermined\n block reward, ``BLOCK_REWARD``, plus a variable award based off of the\n number of ommer blocks that were mined around the same time, and included\n in the canonical block's header. An ommer block is a block that wasn't\n added to the canonical blockchain because it wasn't validated as fast as\n the accepted block but was mined at the same time. Although not all blocks\n that are mined are added to the canonical chain, miners are still paid a\n reward for their efforts. This reward is called an ommer reward and is\n calculated based on the number associated with the ommer block that they\n mined.\n\n Parameters\n ----------\n state :\n Current account state.\n block_number :\n Position of the block within the chain.\n coinbase :\n Address of account which receives block reward and transaction fees.\n ommers :\n List of ommers mentioned in the current block.\n ")), + Assign( + targets=[ + Name(id='ommer_count', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='miner_reward', ctx=Store())], + value=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='ommer_count', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='miner_reward', ctx=Load())], + keywords=[])), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_number', ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='ommer_miner_reward', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Sub(), + right=Name(id='ommer_age', ctx=Load())), + op=Mult(), + right=Name(id='BLOCK_REWARD', ctx=Load())), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='ommer_miner_reward', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + AnnAssign( + target=Name(id='max_gas_fee', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='max_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load())], + keywords=[])))], + orelse=[ + Assign( + targets=[ + Name(id='max_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])))]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='max_gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='effective_gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='effective_gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='preaccessed_addresses', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='preaccessed_storage_keys', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Tuple( + elts=[ + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='address', ctx=Store()), + Name(id='keys', ctx=Store())], + ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='keys', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_storage_keys', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Name(id='address', ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[ + keyword( + arg='preaccessed_addresses', + value=Call( + func=Name(id='frozenset', ctx=Load()), + args=[ + Name(id='preaccessed_addresses', ctx=Load())], + keywords=[])), + keyword( + arg='preaccessed_storage_keys', + value=Call( + func=Name(id='frozenset', ctx=Load()), + args=[ + Name(id='preaccessed_storage_keys', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='priority_fee_per_gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Name(id='priority_fee_per_gas', ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + If( + test=Compare( + left=Name(id='coinbase_balance_after_mining_fee', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]))], + orelse=[])]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='error', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Name(id='TX_CREATE_COST', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Assign( + targets=[ + Name(id='access_list_cost', ctx=Store())], + value=Constant(value=0)), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Tuple( + elts=[ + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='_address', ctx=Store()), + Name(id='keys', ctx=Store())], + ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + body=[ + AugAssign( + target=Name(id='access_list_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_ACCESS_LIST_ADDRESS_COST', ctx=Load())), + AugAssign( + target=Name(id='access_list_cost', ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='keys', ctx=Load())], + keywords=[]), + op=Mult(), + right=Name(id='TX_ACCESS_LIST_STORAGE_KEY_COST', ctx=Load())))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load())), + op=Add(), + right=Name(id='access_list_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=28)])]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash_pre155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='chain_id_x2', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=36)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[])), + op=Sub(), + right=Name(id='chain_id_x2', ctx=Load())), + Call( + func=Name(id='signing_hash_155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])], + keywords=[]))])], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='y_parity', + ctx=Load()), + Call( + func=Name(id='signing_hash_2930', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='y_parity', + ctx=Load()), + Call( + func=Name(id='signing_hash_1559', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])])]), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash_pre155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='LegacyTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a legacy (pre EIP 155) signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='LegacyTransaction', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 155 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n The id of the current chain.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='chain_id', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_2930', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='AccessListTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 2930 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load())], + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_1559', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='FeeMarketTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 1559 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load())], + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_has_ommers', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes difficulty of a block using its header and parent header.\n\n The difficulty is determined by the time the block was created after its\n parent. The ``offset`` is calculated using the parent block's difficulty,\n ``parent_difficulty``, and the timestamp between blocks. This offset is\n then added to the parent difficulty and is stored as the ``difficulty``\n variable. If the time between the block and its parent is too short, the\n offset will result in a positive number thus making the sum of\n ``parent_difficulty`` and ``offset`` to be a greater value in order to\n avoid mass forking. But, if the time is long enough, then the offset\n results in a negative value making the block less difficult than\n its parent.\n\n The base standard for a block's difficulty is the predefined value\n set for the genesis block since it has no parent. So, a block\n can't be less difficult than the genesis block, therefore each block's\n difficulty is set to the maximum value between the calculated\n difficulty and the ``GENESIS_DIFFICULTY``.\n\n Parameters\n ----------\n block_number :\n Block number of the block.\n block_timestamp :\n Timestamp of the block.\n parent_timestamp :\n Timestamp of the parent block.\n parent_difficulty :\n difficulty of the parent block.\n parent_has_ommers:\n does the parent have ommers.\n\n Returns\n -------\n difficulty : `ethereum.base_types.Uint`\n Computed difficulty for a block.\n ")), + Assign( + targets=[ + Name(id='offset', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=2048)), + op=Mult(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=IfExp( + test=Name(id='parent_has_ommers', ctx=Load()), + body=Constant(value=2), + orelse=Constant(value=1)), + op=Sub(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_timestamp', ctx=Load()), + op=Sub(), + right=Name(id='parent_timestamp', ctx=Load()))], + keywords=[]), + op=FloorDiv(), + right=Constant(value=9))), + UnaryOp( + op=USub(), + operand=Constant(value=99))], + keywords=[]))), + Assign( + targets=[ + Name(id='difficulty', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='offset', ctx=Load()))), + Assign( + targets=[ + Name(id='num_bomb_periods', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='BOMB_DELAY_BLOCKS', ctx=Load())), + op=FloorDiv(), + right=Constant(value=100000)), + op=Sub(), + right=Constant(value=2))), + If( + test=Compare( + left=Name(id='num_bomb_periods', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='difficulty', ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Name(id='num_bomb_periods', ctx=Load())))], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='difficulty', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/fork.v b/coq/ethereum/london/fork.v new file mode 100644 index 0000000000..342c6f3b10 --- /dev/null +++ b/coq/ethereum/london/fork.v @@ -0,0 +1,942 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.ethash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.london.__init__. +Require ethereum.london.blocks. +Require ethereum.london.bloom. +Require ethereum.london.fork_types. +Require ethereum.london.state. +Require ethereum.london.transactions. +Require ethereum.london.trie. +Require ethereum.london.utils.message. +Require ethereum.london.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + do* [[ M.get_local ~(| "validate_ommers" |) ~(| + M.get_field ~(| block, "ommers" |), + M.get_field ~(| block, "header" |), + chain + |) ]] in + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "base_fee_per_gas" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "difficulty" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| block, "ommers" |), + M.get_field ~(| chain, "chain_id" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_base_fee_per_gas (block_gas_limit : Uint) (parent_gas_limit : Uint) (parent_gas_used : Uint) (parent_base_fee_per_gas : Uint) : M Uint := + (* + 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. + *) + do* M.assign "parent_gas_target" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + (* TODO statement *) + do* M.assign "expected_base_fee_per_gas" [[ + M.get_local ~(| "INITIAL_BASE_FEE" |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "parent_has_ommers" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_difficulty" [[ + M.get_local ~(| "calculate_block_difficulty" |) ~(| + M.get_field ~(| header, "number" |), + M.get_field ~(| header, "timestamp" |), + M.get_field ~(| parent_header, "timestamp" |), + M.get_field ~(| parent_header, "difficulty" |), + M.get_local ~(| "parent_has_ommers" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| + header + |) ]] in + M.pure tt. + +Definition generate_header_hash_for_pow (header : Header) : M Hash32 := + (* + 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. + *) + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_proof_of_work (header : Header) : M unit := + (* + 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. + *) + do* M.assign "header_hash" [[ + M.get_local ~(| "generate_header_hash_for_pow" |) ~(| + header + |) in + ]] in + do* M.assign "cache" [[ + ethereum.ethash.generate_cache ~(| + M.get_field ~(| header, "number" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (base_fee_per_gas : Uint) (gas_available : Uint) (chain_id : U64) : M (* TODO type *) := + (* + 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. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (error : (* TODO type *)) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (base_fee_per_gas : Uint) (block_gas_limit : Uint) (block_time : U256) (block_difficulty : Uint) (transactions : (* TODO type *)) (ommers : (* TODO type *)) (chain_id : U64) : M ApplyBodyOutput := + (* + 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 + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "pay_rewards" |) ~(| + state, + block_number, + coinbase, + ommers + |) ]] in + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_ommers (ommers : (* TODO type *)) (block_header : Header) (chain : BlockChain) : M unit := + (* + 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. + *) + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_canonical_blocks" [[ + (* TODO expression *) in + ]] in + do* M.assign "recent_canonical_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition pay_rewards (state : State) (block_number : Uint) (coinbase : Address) (ommers : (* TODO type *)) : M unit := + (* + 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. + *) + do* M.assign "ommer_count" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + ommers + |) + |) in + ]] in + do* M.assign "miner_reward" [[ + (* TODO expression *) in + ]] in + do* [[ state.create_ether ~(| + state, + coinbase, + M.get_local ~(| "miner_reward" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "effective_gas_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "preaccessed_addresses" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "preaccessed_storage_keys" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + (* TODO statement *) + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "priority_fee_per_gas" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "access_list_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_pre155 (tx : LegacyTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_155 (tx : LegacyTransaction) (chain_id : U64) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_2930 (tx : AccessListTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_1559 (tx : FeeMarketTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_block_difficulty (block_number : Uint) (block_timestamp : U256) (parent_timestamp : U256) (parent_difficulty : Uint) (parent_has_ommers : bool) : M Uint := + (* + 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. + *) + do* M.assign "offset" [[ + (* TODO expression *) in + ]] in + do* M.assign "difficulty" [[ + (* TODO expression *) in + ]] in + do* M.assign "num_bomb_periods" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/fork_types.ast b/coq/ethereum/london/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/london/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/fork_types.v b/coq/ethereum/london/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/london/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/state.ast b/coq/ethereum/london/state.ast new file mode 100644 index 0000000000..c04909fdce --- /dev/null +++ b/coq/ethereum/london/state.ast @@ -0,0 +1,1692 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='created_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='set', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mark_account_created', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Mark an account as having been created in the current transaction.\n This information is used by `get_storage_original()` to handle an obscure\n edgecase.\n\n The marker is not removed even if the account creation reverts. Since the\n account cannot have had code prior to its creation and can't call\n `get_storage_original()`, this is harmless.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account that has been created.\n ")), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has zero nonce, empty code and zero balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_empty : `bool`\n True if if an account has zero nonce, empty code and zero balance,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_exists_and_is_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists and has zero nonce, empty code and zero\n balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n exists_and_is_empty : `bool`\n True if an account exists and has zero nonce, empty code and zero\n balance, False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='account', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_alive', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether is an account is both in the state and non empty.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_alive : `bool`\n True if the account is alive.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[ + Return( + value=UnaryOp( + op=Not(), + operand=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])])))])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add newly created ether to an account.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to which ether is added.\n amount:\n The amount of ether to be added to the account of interest.\n ')), + FunctionDef( + name='increase_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage_original', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the original value in a storage slot i.e. the value before the current\n transaction began. This function reads the value from the snapshots taken\n before executing the transaction.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to read the value from.\n key:\n Key of the storage slot.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='_', ctx=Store()), + Name(id='original_trie', ctx=Store())], + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + Assign( + targets=[ + Name(id='original_account_trie', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='original_trie', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='original_account_trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='original_account_trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[]))]), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='original_value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='original_value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/state.v b/coq/ethereum/london/state.v new file mode 100644 index 0000000000..924a374914 --- /dev/null +++ b/coq/ethereum/london/state.v @@ -0,0 +1,614 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.london.fork_types. +Require ethereum.london.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition mark_account_created (state : State) (address : Address) : M unit := + (* + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| + address + |) ]] in + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_empty (state : State) (address : Address) : M bool := + (* + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition account_exists_and_is_empty (state : State) (address : Address) : M bool := + (* + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_alive (state : State) (address : Address) : M bool := + (* + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := + (* + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. + +Definition get_storage_original (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + *) + (* TODO statement *) + (* TODO assignment *) + do* M.assign "original_account_trie" [[ + M.get_field ~(| M.get_local ~(| "original_trie" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/transactions.ast b/coq/ethereum/london/transactions.ast new file mode 100644 index 0000000000..264b048f3f --- /dev/null +++ b/coq/ethereum/london/transactions.ast @@ -0,0 +1,492 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='TransactionTypeError')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + Assign( + targets=[ + Name(id='TX_ACCESS_LIST_ADDRESS_COST', ctx=Store())], + value=Constant(value=2400)), + Assign( + targets=[ + Name(id='TX_ACCESS_LIST_STORAGE_KEY_COST', ctx=Store())], + value=Constant(value=1900)), + ClassDef( + name='LegacyTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='AccessListTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The transaction type added in EIP-2930 to support access lists.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='access_list', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y_parity', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='FeeMarketTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The transaction type added in EIP-1559.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_priority_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='access_list', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y_parity', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='Transaction', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Encode a transaction. Needed because non-legacy transactions aren't RLP.\n ")), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='tx', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])))], + orelse=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Unable to encode transaction of type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + conversion=-1)])], + keywords=[]))])])])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='decode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Decode a transaction. Needed because non-legacy transactions aren't RLP.\n ")), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Name(id='AccessListTransaction', ctx=Load()), + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=2)]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Name(id='FeeMarketTransaction', ctx=Load()), + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())], + keywords=[]))], + orelse=[ + Raise( + exc=Call( + func=Name(id='TransactionTypeError', ctx=Load()), + args=[ + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]))])])], + orelse=[ + Return( + value=Name(id='tx', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Transaction', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/transactions.v b/coq/ethereum/london/transactions.v new file mode 100644 index 0000000000..94a6572eb2 --- /dev/null +++ b/coq/ethereum/london/transactions.v @@ -0,0 +1,29 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.london.exceptions. +Require ethereum.london.fork_types. + +Definition encode_transaction (tx : Transaction) : M (* TODO type *) := + (* + Encode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + M.pure tt. + +Definition decode_transaction (tx : (* TODO type *)) : M Transaction := + (* + Decode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/trie.ast b/coq/ethereum/london/trie.ast new file mode 100644 index 0000000000..3db7e962d7 --- /dev/null +++ b/coq/ethereum/london/trie.ast @@ -0,0 +1,1632 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.berlin', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='LegacyTransaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Receipt', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.RLP`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/trie.v b/coq/ethereum/london/trie.v new file mode 100644 index 0000000000..6b8953f256 --- /dev/null +++ b/coq/ethereum/london/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/utils/__init__.ast b/coq/ethereum/london/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/london/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/utils/__init__.v b/coq/ethereum/london/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/london/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/london/utils/address.ast b/coq/ethereum/london/utils/address.ast new file mode 100644 index 0000000000..dc3a4de3e2 --- /dev/null +++ b/coq/ethereum/london/utils/address.ast @@ -0,0 +1,216 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this london version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_create2_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='salt', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='call_data', + annotation=Name(id='bytearray', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created, which is\n based on the sender address, salt and the call data as well.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n salt :\n Address generation salt.\n call_data :\n The code of the new account which is to be created.\n\n Returns\n -------\n address: `ethereum.london.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='preimage', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Constant(value=b'\xff'), + op=Add(), + right=Name(id='address', ctx=Load())), + op=Add(), + right=Name(id='salt', ctx=Load())), + op=Add(), + right=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='call_data', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/utils/address.v b/coq/ethereum/london/utils/address.v new file mode 100644 index 0000000000..d258fab837 --- /dev/null +++ b/coq/ethereum/london/utils/address.v @@ -0,0 +1,115 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this london version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.london.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition compute_create2_contract_address (address : Address) (salt : Bytes32) (call_data : bytearray) : M Address := + (* + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.london.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "preimage" [[ + (* TODO expression *) in + ]] in + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "preimage" |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/utils/hexadecimal.ast b/coq/ethereum/london/utils/hexadecimal.ast new file mode 100644 index 0000000000..4067be5dae --- /dev/null +++ b/coq/ethereum/london/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to\nLondon types.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/utils/hexadecimal.v b/coq/ethereum/london/utils/hexadecimal.v new file mode 100644 index 0000000000..61730ba174 --- /dev/null +++ b/coq/ethereum/london/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +London types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.london.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/utils/message.ast b/coq/ethereum/london/utils/message.ast new file mode 100644 index 0000000000..97b94bb52d --- /dev/null +++ b/coq/ethereum/london/utils/message.ast @@ -0,0 +1,335 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this london version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='FrozenSet'), + alias(name='Optional'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_static', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='preaccessed_addresses', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='preaccessed_storage_keys', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True), + Constant(value=False), + Call( + func=Name(id='frozenset', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='frozenset', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n is_static:\n if True then it prevents all state-changing operations from being\n executed.\n preaccessed_addresses:\n Addresses that should be marked as accessed prior to the message call\n preaccessed_storage_keys:\n Storage keys that should be marked as accessed prior to the message\n call\n\n Returns\n -------\n message: `ethereum.london.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Assign( + targets=[ + Name(id='accessed_addresses', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='current_target', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='caller', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Name(id='preaccessed_addresses', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=Name(id='is_static', ctx=Load())), + keyword( + arg='accessed_addresses', + value=Name(id='accessed_addresses', ctx=Load())), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='preaccessed_storage_keys', ctx=Load())], + keywords=[])), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/utils/message.v b/coq/ethereum/london/utils/message.v new file mode 100644 index 0000000000..56215e8a73 --- /dev/null +++ b/coq/ethereum/london/utils/message.v @@ -0,0 +1,85 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this london version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.london.fork_types. +Require ethereum.london.state. +Require ethereum.london.vm. +Require ethereum.london.vm.precompiled_contracts.mapping. +Require ethereum.london.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) (is_static : bool) (preaccessed_addresses : (* TODO type *)) (preaccessed_storage_keys : (* TODO type *)) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.london.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + do* M.assign "accessed_addresses" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "add" |) ~(| + M.get_local ~(| "current_target" |) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "add" |) ~(| + caller + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS, "keys" |) ~(| + + |) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + preaccessed_addresses + |) ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/vm/__init__.ast b/coq/ethereum/london/vm/__init__.ast new file mode 100644 index 0000000000..5290882162 --- /dev/null +++ b/coq/ethereum/london/vm/__init__.ast @@ -0,0 +1,591 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty')], + level=2), + ImportFrom( + module='precompiled_contracts', + names=[ + alias(name='RIPEMD160_ADDRESS')], + level=1), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='is_static', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_addresses', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_storage_keys', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='return_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_addresses', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_storage_keys', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + If( + test=Compare( + left=Name(id='RIPEMD160_ADDRESS', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/__init__.v b/coq/ethereum/london/vm/__init__.v new file mode 100644 index 0000000000..c17fd4816f --- /dev/null +++ b/coq/ethereum/london/vm/__init__.v @@ -0,0 +1,78 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.london.blocks. +Require ethereum.london.fork_types. +Require ethereum.london.state. +Require ethereum.london.vm.precompiled_contracts. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "touched_accounts" |), "update" |) ~(| + M.get_field ~(| child_evm, "touched_accounts" |) + |) ]] in + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| child_evm, "accessed_addresses" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_storage_keys" |), "update" |) ~(| + M.get_field ~(| child_evm, "accessed_storage_keys" |) + |) ]] in + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + (* TODO statement *) + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/london/vm/exceptions.ast b/coq/ethereum/london/vm/exceptions.ast new file mode 100644 index 0000000000..79ecb4b47d --- /dev/null +++ b/coq/ethereum/london/vm/exceptions.ast @@ -0,0 +1,175 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='Revert', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised by the `REVERT` opcode.\n\n Unlike other EVM exceptions this does not result in the consumption of all\n gas.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='WriteInStaticContext', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt is made to modify the state while operating inside\n of a STATICCALL context.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfBoundsRead', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt was made to read data beyond the\n boundaries of the buffer.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidParameter', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when invalid parameters are passed.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidContractPrefix', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract code starts with 0xEF.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/exceptions.v b/coq/ethereum/london/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/london/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/london/vm/gas.ast b/coq/ethereum/london/vm/gas.ast new file mode 100644 index 0000000000..33b4cae82f --- /dev/null +++ b/coq/ethereum/london/vm/gas.ast @@ -0,0 +1,813 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=4800)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RETURN_DATA_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_FAST_STEP', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLAKE2_PER_ROUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COLD_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2100)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_WARM_ACCESS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=100)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_left', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='memory_cost', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='extra_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='call_stipend', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Expr( + value=Constant(value='\n Calculates the MessageCallGas (cost and stipend) for\n executing call Opcodes.\n\n Parameters\n ----------\n value:\n The amount of `ETH` that needs to be transferred.\n gas :\n The amount of gas provided to the message-call.\n gas_left :\n The amount of gas left in the current frame.\n memory_cost :\n The amount needed to extend the memory in the current frame.\n extra_gas :\n The amount of gas needed for transferring value + creating a new\n account inside a message call.\n call_stipend :\n The amount of stipend provided to a message call to execute code while\n transferring value(ETH).\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='call_stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='call_stipend', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='extra_gas', ctx=Load()), + op=Add(), + right=Name(id='memory_cost', ctx=Load()))]), + body=[ + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='gas', ctx=Load()), + Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='gas_left', ctx=Load()), + op=Sub(), + right=Name(id='memory_cost', ctx=Load())), + op=Sub(), + right=Name(id='extra_gas', ctx=Load()))], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load())), + FunctionDef( + name='max_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the maximum gas that is allowed for making a message call\n\n Parameters\n ----------\n gas :\n The amount of gas provided to the message-call.\n\n Returns\n -------\n max_allowed_message_call_gas: `ethereum.base_types.Uint`\n The maximum gas allowed for making the message-call.\n ')), + Return( + value=BinOp( + left=Name(id='gas', ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='gas', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]))))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/gas.v b/coq/ethereum/london/vm/gas.v new file mode 100644 index 0000000000..d43f8161ea --- /dev/null +++ b/coq/ethereum/london/vm/gas.v @@ -0,0 +1,171 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (value : U256) (gas : Uint) (gas_left : Uint) (memory_cost : Uint) (extra_gas : Uint) (call_stipend : Uint) : M MessageCallGas := + (* + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "gas" [[ + M.get_local ~(| "min" |) ~(| + gas, + M.get_local ~(| "max_message_call_gas" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition max_message_call_gas (gas : Uint) : M Uint := + (* + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/vm/instructions/__init__.ast b/coq/ethereum/london/vm/instructions/__init__.ast new file mode 100644 index 0000000000..5dae83fbf2 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/__init__.ast @@ -0,0 +1,1792 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='SHL', ctx=Store())], + value=Constant(value=27)), + Assign( + targets=[ + Name(id='SHR', ctx=Store())], + value=Constant(value=28)), + Assign( + targets=[ + Name(id='SAR', ctx=Store())], + value=Constant(value=29)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='RETURNDATASIZE', ctx=Store())], + value=Constant(value=61)), + Assign( + targets=[ + Name(id='RETURNDATACOPY', ctx=Store())], + value=Constant(value=62)), + Assign( + targets=[ + Name(id='EXTCODEHASH', ctx=Store())], + value=Constant(value=63)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='DIFFICULTY', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='CHAINID', ctx=Store())], + value=Constant(value=70)), + Assign( + targets=[ + Name(id='SELFBALANCE', ctx=Store())], + value=Constant(value=71)), + Assign( + targets=[ + Name(id='BASEFEE', ctx=Store())], + value=Constant(value=72)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='CREATE2', ctx=Store())], + value=Constant(value=245)), + Assign( + targets=[ + Name(id='STATICCALL', ctx=Store())], + value=Constant(value=250)), + Assign( + targets=[ + Name(id='REVERT', ctx=Store())], + value=Constant(value=253)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SAR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIFFICULTY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CHAINID', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODEHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFBALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BASEFEE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STATICCALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='REVERT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE2', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shl', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shr', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_sar', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodehash', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='self_balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='base_fee', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='staticcall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='revert', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create2', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/instructions/__init__.v b/coq/ethereum/london/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/london/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/london/vm/instructions/arithmetic.ast b/coq/ethereum/london/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/instructions/arithmetic.v b/coq/ethereum/london/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..d063a4b96d --- /dev/null +++ b/coq/ethereum/london/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/london/vm/instructions/bitwise.ast b/coq/ethereum/london/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..b72397f0ec --- /dev/null +++ b/coq/ethereum/london/vm/instructions/bitwise.ast @@ -0,0 +1,751 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shl', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift left (SHL) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='value', ctx=Load()), + op=LShift(), + right=Name(id='shift', ctx=Load())), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]))], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shr', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift right (SHR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_sar', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Arithmetic shift right (SAR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='signed_value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=256)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + BinOp( + left=Name(id='signed_value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load()))], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='signed_value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load()))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/instructions/bitwise.v b/coq/ethereum/london/vm/instructions/bitwise.v new file mode 100644 index 0000000000..7768d2fde4 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/bitwise.v @@ -0,0 +1,309 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shl (evm : Evm) : M unit := + (* + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shr (evm : Evm) : M unit := + (* + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_sar (evm : Evm) : M unit := + (* + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + M.get_local ~(| "int" |) ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "signed_value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/london/vm/instructions/block.ast b/coq/ethereum/london/vm/instructions/block.ast new file mode 100644 index 0000000000..b9ccb3290b --- /dev/null +++ b/coq/ethereum/london/vm/instructions/block.ast @@ -0,0 +1,492 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's difficulty onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='chain_id', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the chain id onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/instructions/block.v b/coq/ethereum/london/vm/instructions/block.v new file mode 100644 index 0000000000..e4a1c93552 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/block.v @@ -0,0 +1,241 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition difficulty (evm : Evm) : M unit := + (* + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition chain_id (evm : Evm) : M unit := + (* + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/london/vm/instructions/comparison.ast b/coq/ethereum/london/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/instructions/comparison.v b/coq/ethereum/london/vm/instructions/comparison.v new file mode 100644 index 0000000000..996662ec08 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/london/vm/instructions/control_flow.ast b/coq/ethereum/london/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/instructions/control_flow.v b/coq/ethereum/london/vm/instructions/control_flow.v new file mode 100644 index 0000000000..3355af2430 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.exceptions. +Require ethereum.london.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/london/vm/instructions/environment.ast b/coq/ethereum/london/vm/instructions/environment.ast new file mode 100644 index 0000000000..60bbfdaff1 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/environment.ast @@ -0,0 +1,1828 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfBoundsRead')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_COLD_ACCOUNT_ACCESS'), + alias(name='GAS_COPY'), + alias(name='GAS_FAST_STEP'), + alias(name='GAS_RETURN_DATA_COPY'), + alias(name='GAS_VERY_LOW'), + alias(name='GAS_WARM_ACCESS'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_WARM_ACCESS', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the size of the return data buffer onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copies data from the return data buffer code to memory\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='return_data_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_RETURN_DATA_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='return_data_start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfBoundsRead', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load()), + slice=Slice( + lower=Name(id='return_data_start_position', ctx=Load()), + upper=BinOp( + left=Name(id='return_data_start_position', ctx=Load()), + op=Add(), + right=Name(id='size', ctx=Load()))), + ctx=Load())), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodehash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns the keccak256 hash of a contract’s bytecode\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='EMPTY_ACCOUNT', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codehash', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='self_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the current address to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_FAST_STEP', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='base_fee', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the base fee of the current block on to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/instructions/environment.v b/coq/ethereum/london/vm/instructions/environment.v new file mode 100644 index 0000000000..20b6c36c3f --- /dev/null +++ b/coq/ethereum/london/vm/instructions/environment.v @@ -0,0 +1,728 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.london.fork_types. +Require ethereum.london.state. +Require ethereum.london.utils.address. +Require ethereum.london.vm.memory. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.exceptions. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatasize (evm : Evm) : M unit := + (* + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatacopy (evm : Evm) : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "return_data_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + (* TODO expression *) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodehash (evm : Evm) : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "account" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codehash" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition self_balance (evm : Evm) : M unit := + (* + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_FAST_STEP + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition base_fee (evm : Evm) : M unit := + (* + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "base_fee_per_gas" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/london/vm/instructions/keccak.ast b/coq/ethereum/london/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/instructions/keccak.v b/coq/ethereum/london/vm/instructions/keccak.v new file mode 100644 index 0000000000..e03f22a1fc --- /dev/null +++ b/coq/ethereum/london/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.memory. +Require ethereum.london.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/london/vm/instructions/log.ast b/coq/ethereum/london/vm/instructions/log.ast new file mode 100644 index 0000000000..0ded0e04ba --- /dev/null +++ b/coq/ethereum/london/vm/instructions/log.ast @@ -0,0 +1,323 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/instructions/log.v b/coq/ethereum/london/vm/instructions/log.v new file mode 100644 index 0000000000..737e1cd8b1 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/log.v @@ -0,0 +1,79 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.london.blocks. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.exceptions. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.memory. +Require ethereum.london.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO statement *) + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/london/vm/instructions/memory.ast b/coq/ethereum/london/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/instructions/memory.v b/coq/ethereum/london/vm/instructions/memory.v new file mode 100644 index 0000000000..66ae2a82e0 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.memory. +Require ethereum.london.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/london/vm/instructions/stack.ast b/coq/ethereum/london/vm/instructions/stack.ast new file mode 100644 index 0000000000..95cfc0b6cf --- /dev/null +++ b/coq/ethereum/london/vm/instructions/stack.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/instructions/stack.v b/coq/ethereum/london/vm/instructions/stack.v new file mode 100644 index 0000000000..978d31e276 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/stack.v @@ -0,0 +1,153 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.exceptions. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/london/vm/instructions/storage.ast b/coq/ethereum/london/vm/instructions/storage.ast new file mode 100644 index 0000000000..68640a90a8 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/storage.ast @@ -0,0 +1,551 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='get_storage_original'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_STIPEND'), + alias(name='GAS_COLD_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='GAS_WARM_ACCESS'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_SLOAD', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='get_storage_original', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + If( + test=Compare( + left=Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_COLD_SLOAD', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='current_value', ctx=Load())]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())])]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_COLD_SLOAD', ctx=Load())))])], + orelse=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))]), + If( + test=Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='GAS_STORAGE_SET', ctx=Load()), + op=Sub(), + right=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + keywords=[]))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_COLD_SLOAD', ctx=Load())), + op=Sub(), + right=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + keywords=[]))])], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/instructions/storage.v b/coq/ethereum/london/vm/instructions/storage.v new file mode 100644 index 0000000000..3af6be38e8 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/storage.v @@ -0,0 +1,121 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.london.state. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.exceptions. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "original_value" [[ + state.get_storage_original ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "gas_cost" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/london/vm/instructions/system.ast b/coq/ethereum/london/vm/instructions/system.ast new file mode 100644 index 0000000000..0fcb1135df --- /dev/null +++ b/coq/ethereum/london/vm/instructions/system.ast @@ -0,0 +1,2897 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='is_account_alive'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='compute_create2_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='Revert'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_VALUE'), + alias(name='GAS_COLD_ACCOUNT_ACCESS'), + alias(name='GAS_CREATE'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='GAS_NEW_ACCOUNT'), + alias(name='GAS_SELF_DESTRUCT'), + alias(name='GAS_SELF_DESTRUCT_NEW_ACCOUNT'), + alias(name='GAS_WARM_ACCESS'), + alias(name='GAS_ZERO'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas'), + alias(name='max_message_call_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='generic_create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='endowment', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='contract_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='memory_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Core logic used by the `CREATE*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='contract_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='create_message_gas', ctx=Load())), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='is_static', + value=Constant(value=False)), + keyword( + arg='accessed_addresses', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create2', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Creates a new account with associated code.\n\n It's similar to CREATE opcode except that the address of new account\n depends on the init_code instead of the nonce of sender.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ")), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='salt', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='call_data_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='call_data_words', ctx=Load()))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_create2_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='salt', ctx=Load()), + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_staticcall', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=IfExp( + test=Name(id='is_staticcall', ctx=Load()), + body=Constant(value=True), + orelse=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()))), + keyword( + arg='accessed_addresses', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='to', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=BoolOp( + op=Or(), + values=[ + Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[]), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='access_gas_cost', ctx=Load()), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='code_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=Name(id='access_gas_cost', ctx=Load()), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SELF_DESTRUCT', ctx=Load())), + If( + test=Compare( + left=Name(id='beneficiary', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[])), + Compare( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='code_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='access_gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='staticcall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='to', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='access_gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='revert', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop execution and revert state changes, without consuming all provided gas\n and also has the ability to return a reason\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Name(id='output', ctx=Load())], + keywords=[])), + Raise( + exc=Name(id='Revert', ctx=Load())), + Pass()], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/instructions/system.v b/coq/ethereum/london/vm/instructions/system.v new file mode 100644 index 0000000000..e55d0db7e8 --- /dev/null +++ b/coq/ethereum/london/vm/instructions/system.v @@ -0,0 +1,779 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.london.fork_types. +Require ethereum.london.state. +Require ethereum.london.utils.address. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.exceptions. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.memory. +Require ethereum.london.vm.stack. + +Definition generic_create (evm : Evm) (endowment : U256) (contract_address : Address) (memory_start_position : U256) (memory_size : U256) : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "add" |) ~(| + contract_address + |) ]] in + do* M.assign "create_message_gas" [[ + gas.max_message_call_gas ~(| + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) in + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_local ~(| "create_message_gas" |) + ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_start_position, + memory_size + |) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_create_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition create2 (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "salt" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "call_data_words" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_create2_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "salt" |), + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (is_staticcall : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_SELF_DESTRUCT in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + M.get_local ~(| "access_gas_cost" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition staticcall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + M.get_local ~(| "access_gas_cost" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "to" |), + M.get_local ~(| "to" |), + True, + True, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition revert (evm : Evm) : M unit := + (* + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "output" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/vm/interpreter.ast b/coq/ethereum/london/vm/interpreter.ast new file mode 100644 index 0000000000..6411a26545 --- /dev/null +++ b/coq/ethereum/london/vm/interpreter.ast @@ -0,0 +1,1177 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Iterable'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='increment_nonce'), + alias(name='mark_account_created'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidContractPrefix'), + alias(name='InvalidOpcode'), + alias(name='OutOfGasError'), + alias(name='Revert'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_CODE_SIZE', ctx=Store())], + value=Constant(value=24576)), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `touched_accounts`: Accounts that have been touched.\n 6. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='touched_accounts', + value=Name(id='touched_accounts', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.london.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='mark_account_created', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='contract_code', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=239)]), + body=[ + Raise( + exc=Name(id='InvalidContractPrefix', ctx=Load()))], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_CODE_SIZE', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.london.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='touched_accounts', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='return_data', + value=Constant(value=b'')), + keyword( + arg='error', + value=Constant(value=None)), + keyword( + arg='accessed_addresses', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='accessed_addresses', + ctx=Load())), + keyword( + arg='accessed_storage_keys', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))]), + ExceptHandler( + type=Name(id='Revert', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/interpreter.v b/coq/ethereum/london/vm/interpreter.v new file mode 100644 index 0000000000..763d506e64 --- /dev/null +++ b/coq/ethereum/london/vm/interpreter.v @@ -0,0 +1,173 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.london.blocks. +Require ethereum.london.fork_types. +Require ethereum.london.state. +Require ethereum.london.vm. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.precompiled_contracts.mapping. +Require ethereum.london.vm.__init__. +Require ethereum.london.vm.exceptions. +Require ethereum.london.vm.instructions. +Require ethereum.london.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.mark_account_created ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.london.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/vm/memory.ast b/coq/ethereum/london/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/london/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/memory.v b/coq/ethereum/london/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/london/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/vm/precompiled_contracts/__init__.ast b/coq/ethereum/london/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..bb9991907f --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS'), + Constant(value='MODEXP_ADDRESS'), + Constant(value='ALT_BN128_ADD_ADDRESS'), + Constant(value='ALT_BN128_MUL_ADDRESS'), + Constant(value='ALT_BN128_PAIRING_CHECK_ADDRESS'), + Constant(value='BLAKE2F_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[])), + Assign( + targets=[ + Name(id='MODEXP_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x05')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x06')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x07')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x08')], + keywords=[])), + Assign( + targets=[ + Name(id='BLAKE2F_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x09')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/precompiled_contracts/__init__.v b/coq/ethereum/london/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..6e2810bd75 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.london.utils.hexadecimal. diff --git a/coq/ethereum/london/vm/precompiled_contracts/alt_bn128.ast b/coq/ethereum/london/vm/precompiled_contracts/alt_bn128.ast new file mode 100644 index 0000000000..f6f077419c --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/alt_bn128.ast @@ -0,0 +1,913 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ALT_BN128 CONTRACTS\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ALT_BN128 precompiled contracts.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.alt_bn128', + names=[ + alias(name='ALT_BN128_CURVE_ORDER'), + alias(name='ALT_BN128_PRIME'), + alias(name='BNF'), + alias(name='BNF2'), + alias(name='BNF12'), + alias(name='BNP'), + alias(name='BNP2'), + alias(name='pairing')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=2), + FunctionDef( + name='alt_bn128_add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 addition precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=150)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load()), + Name(id='x1_value', ctx=Load()), + Name(id='y1_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='p1', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x1_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y1_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=BinOp( + left=Name(id='p0', ctx=Load()), + op=Add(), + right=Name(id='p1', ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 multiplication precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6000)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='n', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='p0', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='n', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_pairing_check', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 pairing check precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=34000), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))), + op=Add(), + right=Constant(value=45000))], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=192)), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='values', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=Name(id='j', ctx=Load()))), + upper=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=BinOp( + left=Name(id='j', ctx=Load()), + op=Add(), + right=Constant(value=1))))), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='values', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=Call( + func=Name(id='BNP2', ctx=Load()), + args=[ + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=3), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=2), + ctx=Load())], + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=5), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=4), + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='OutOfGasError', ctx=Load()), + args=[], + keywords=[]))])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='p', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='q', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='p', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + Compare( + left=Name(id='q', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='result', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='pairing', ctx=Load()), + args=[ + Name(id='q', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[])))], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='result', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/london/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000000..f699b9321a --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,226 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.alt_bn128. +Require ethereum.london.vm. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.memory. +Require ethereum.london.vm.exceptions. + +Definition alt_bn128_add (evm : Evm) : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 150 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "x1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x1_bytes" |) + |) + |) in + ]] in + do* M.assign "y1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y1_bytes" |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + (* TODO expression *) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_mul (evm : Evm) : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 6000 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "n" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + M.get_field ~(| M.get_local ~(| "p0" |), "mul_by" |) ~(| + M.get_local ~(| "n" |) + |) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_pairing_check (evm : Evm) : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + (* TODO expression *) + |) + |) ]] in + (* TODO statement *) + do* M.assign "result" [[ + M.get_field ~(| ethereum.crypto.alt_bn128.BNF12, "from_int" |) ~(| + 1 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/vm/precompiled_contracts/blake2f.ast b/coq/ethereum/london/vm/precompiled_contracts/blake2f.ast new file mode 100644 index 0000000000..03747962f0 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/blake2f.ast @@ -0,0 +1,137 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `Blake2` precompiled contract.\n')), + ImportFrom( + module='ethereum.crypto.blake2', + names=[ + alias(name='Blake2b')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BLAKE2_PER_ROUND'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidParameter')], + level=2), + FunctionDef( + name='blake2f', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the Blake2 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Constant(value=213)]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='blake2b', ctx=Store())], + value=Call( + func=Name(id='Blake2b', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='rounds', ctx=Store()), + Name(id='h', ctx=Store()), + Name(id='m', ctx=Store()), + Name(id='t_0', ctx=Store()), + Name(id='t_1', ctx=Store()), + Name(id='f', ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='get_blake2_parameters', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_BLAKE2_PER_ROUND', ctx=Load()), + op=Mult(), + right=Name(id='rounds', ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=Name(id='f', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + List( + elts=[ + Constant(value=0), + Constant(value=1)], + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='compress', + ctx=Load()), + args=[ + Name(id='rounds', ctx=Load()), + Name(id='h', ctx=Load()), + Name(id='m', ctx=Load()), + Name(id='t_0', ctx=Load()), + Name(id='t_1', ctx=Load()), + Name(id='f', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/precompiled_contracts/blake2f.v b/coq/ethereum/london/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000000..bde9d97f03 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,46 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +*) + +Require ethereum.crypto.blake2. +Require ethereum.london.vm. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.exceptions. + +Definition blake2f (evm : Evm) : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + (* TODO statement *) + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| + + |) in + ]] in + (* TODO assignment *) + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/london/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/london/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/london/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..1e7530ad14 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.london.vm. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/london/vm/precompiled_contracts/identity.ast b/coq/ethereum/london/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/precompiled_contracts/identity.v b/coq/ethereum/london/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..ea3b810ae4 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.london.vm. +Require ethereum.london.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/london/vm/precompiled_contracts/mapping.ast b/coq/ethereum/london/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..cec40e5736 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ALT_BN128_ADD_ADDRESS'), + alias(name='ALT_BN128_MUL_ADDRESS'), + alias(name='ALT_BN128_PAIRING_CHECK_ADDRESS'), + alias(name='BLAKE2F_ADDRESS'), + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='MODEXP_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='alt_bn128', + names=[ + alias(name='alt_bn128_add'), + alias(name='alt_bn128_mul'), + alias(name='alt_bn128_pairing_check')], + level=1), + ImportFrom( + module='blake2f', + names=[ + alias(name='blake2f')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='modexp', + names=[ + alias(name='modexp')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load()), + Name(id='MODEXP_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Load()), + Name(id='BLAKE2F_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load()), + Name(id='modexp', ctx=Load()), + Name(id='alt_bn128_add', ctx=Load()), + Name(id='alt_bn128_mul', ctx=Load()), + Name(id='alt_bn128_pairing_check', ctx=Load()), + Name(id='blake2f', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/precompiled_contracts/mapping.v b/coq/ethereum/london/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..3ea5f796d0 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/mapping.v @@ -0,0 +1,25 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.london.fork_types. +Require ethereum.london.vm.precompiled_contracts.__init__. +Require ethereum.london.vm.precompiled_contracts.alt_bn128. +Require ethereum.london.vm.precompiled_contracts.blake2f. +Require ethereum.london.vm.precompiled_contracts.ecrecover. +Require ethereum.london.vm.precompiled_contracts.identity. +Require ethereum.london.vm.precompiled_contracts.modexp. +Require ethereum.london.vm.precompiled_contracts.ripemd160. +Require ethereum.london.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/london/vm/precompiled_contracts/modexp.ast b/coq/ethereum/london/vm/precompiled_contracts/modexp.ast new file mode 100644 index 0000000000..42ecfa223f --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/modexp.ast @@ -0,0 +1,638 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `MODEXP` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + Assign( + targets=[ + Name(id='GQUADDIVISOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + FunctionDef( + name='modexp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and.\n `modulus`. The return value is the same length as the modulus.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='base_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_start', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Add(), + right=Name(id='base_length', ctx=Load()))), + Assign( + targets=[ + Name(id='exp_head', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Call( + func=Name(id='min', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='gas_cost', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load()), + Name(id='exp_length', ctx=Load()), + Name(id='exp_head', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='base_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='modulus_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Name(id='base_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_start', ctx=Store())], + value=BinOp( + left=Name(id='exp_start', ctx=Load()), + op=Add(), + right=Name(id='exp_length', ctx=Load()))), + Assign( + targets=[ + Name(id='modulus', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='modulus_start', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='modulus', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'\x00')], + keywords=[]), + op=Mult(), + right=Name(id='modulus_length', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exp', ctx=Load()), + Name(id='modulus', ctx=Load())], + keywords=[]), + attr='to_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[]), + Constant(value='big')], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='complexity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Estimate the complexity of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n Returns\n -------\n\n complexity : `Uint`\n Complexity of performing the operation.\n ')), + Assign( + targets=[ + Name(id='max_length', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load())], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Return( + value=BinOp( + left=Name(id='words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='iterations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the number of iterations required to perform a modular\n exponentiation.\n\n Parameters\n ----------\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n iterations : `Uint`\n Number of iterations.\n ')), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + Compare( + left=Name(id='exponent_head', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='bit_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='bit_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='bit_length', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Name(id='bit_length', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='length_part', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])))), + Assign( + targets=[ + Name(id='bits_part', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='bits_part', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='bits_part', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=BinOp( + left=Name(id='length_part', ctx=Load()), + op=Add(), + right=Name(id='bits_part', ctx=Load())))])]), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='count', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the gas cost of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n gas_cost : `Uint`\n Gas required for performing the operation.\n ')), + Assign( + targets=[ + Name(id='multiplication_complexity', ctx=Store())], + value=Call( + func=Name(id='complexity', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='iteration_count', ctx=Store())], + value=Call( + func=Name(id='iterations', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load()), + Name(id='exponent_head', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cost', ctx=Store())], + value=BinOp( + left=Name(id='multiplication_complexity', ctx=Load()), + op=Mult(), + right=Name(id='iteration_count', ctx=Load()))), + AugAssign( + target=Name(id='cost', ctx=Store()), + op=FloorDiv(), + value=Name(id='GQUADDIVISOR', ctx=Load())), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[]), + Name(id='cost', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/precompiled_contracts/modexp.v b/coq/ethereum/london/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000000..ec7667d338 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/modexp.v @@ -0,0 +1,236 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.london.vm. +Require ethereum.london.vm.gas. +Require ethereum.london.vm.memory. + +Definition modexp (evm : Evm) : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "base_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "modulus_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "exp_head" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "min" |) ~(| + ethereum_types.numeric.U256 ~(| + 32 + |), + M.get_local ~(| "exp_length" |) + |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) ~(| + M.get_local ~(| "base_length" |), + M.get_local ~(| "modulus_length" |), + M.get_local ~(| "exp_length" |), + M.get_local ~(| "exp_head" |) + |) + |) ]] in + (* TODO statement *) + do* M.assign "base" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + M.get_local ~(| "base_length" |) + |) + |) in + ]] in + do* M.assign "exp" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "exp_length" |) + |) + |) in + ]] in + do* M.assign "modulus_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "modulus" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "modulus_start" |), + M.get_local ~(| "modulus_length" |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := + (* + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + *) + do* M.assign "max_length" [[ + M.get_local ~(| "max" |) ~(| + ethereum_types.numeric.Uint ~(| + base_length + |), + ethereum_types.numeric.Uint ~(| + modulus_length + |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition gas_cost (base_length : U256) (modulus_length : U256) (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + *) + do* M.assign "multiplication_complexity" [[ + M.get_local ~(| "complexity" |) ~(| + base_length, + modulus_length + |) in + ]] in + do* M.assign "iteration_count" [[ + M.get_local ~(| "iterations" |) ~(| + exponent_length, + exponent_head + |) in + ]] in + do* M.assign "cost" [[ + (* TODO expression *) in + ]] in + do* M.aug_assign [[ M.get_local ~(| "cost" |) ]] [[ + M.get_local ~(| "GQUADDIVISOR" |) + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/london/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/london/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/london/vm/precompiled_contracts/sha256.ast b/coq/ethereum/london/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/precompiled_contracts/sha256.v b/coq/ethereum/london/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/london/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/london/vm/runtime.ast b/coq/ethereum/london/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/london/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/runtime.v b/coq/ethereum/london/vm/runtime.v new file mode 100644 index 0000000000..c62fb345c2 --- /dev/null +++ b/coq/ethereum/london/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.london.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/london/vm/stack.ast b/coq/ethereum/london/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/london/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/london/vm/stack.v b/coq/ethereum/london/vm/stack.v new file mode 100644 index 0000000000..d0e6b6e1dd --- /dev/null +++ b/coq/ethereum/london/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.london.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/__init__.ast b/coq/ethereum/muir_glacier/__init__.ast new file mode 100644 index 0000000000..fa6a34bb6a --- /dev/null +++ b/coq/ethereum/muir_glacier/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe Muir Glacier fork delays the difficulty bomb. There are no other changes\nin this fork.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=9200000)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/__init__.v b/coq/ethereum/muir_glacier/__init__.v new file mode 100644 index 0000000000..80494e48e6 --- /dev/null +++ b/coq/ethereum/muir_glacier/__init__.v @@ -0,0 +1,7 @@ +(* Generated *) +(* +The Muir Glacier fork delays the difficulty bomb. There are no other changes +in this fork. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/muir_glacier/blocks.ast b/coq/ethereum/muir_glacier/blocks.ast new file mode 100644 index 0000000000..bcca95bdaa --- /dev/null +++ b/coq/ethereum/muir_glacier/blocks.ast @@ -0,0 +1,218 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mix_digest', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='succeeded', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/blocks.v b/coq/ethereum/muir_glacier/blocks.v new file mode 100644 index 0000000000..97352b0946 --- /dev/null +++ b/coq/ethereum/muir_glacier/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.muir_glacier.fork_types. +Require ethereum.muir_glacier.transactions. diff --git a/coq/ethereum/muir_glacier/bloom.ast b/coq/ethereum/muir_glacier/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/muir_glacier/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/bloom.v b/coq/ethereum/muir_glacier/bloom.v new file mode 100644 index 0000000000..04e052342c --- /dev/null +++ b/coq/ethereum/muir_glacier/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.muir_glacier.blocks. +Require ethereum.muir_glacier.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/fork.ast b/coq/ethereum/muir_glacier/fork.ast new file mode 100644 index 0000000000..a6b719fefb --- /dev/null +++ b/coq/ethereum/muir_glacier/fork.ast @@ -0,0 +1,3189 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.ethash', + names=[ + alias(name='dataset_size'), + alias(name='generate_cache'), + alias(name='hashimoto_light')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty'), + alias(name='create_ether'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='Transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BLOCK_REWARD', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=18)))], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=131072)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_OMMER_DEPTH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='BOMB_DELAY_BLOCKS', ctx=Store())], + value=Constant(value=9000000)), + Assign( + targets=[ + Name(id='EMPTY_OMMER_HASH', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List(elts=[], ctx=Load())], + keywords=[])], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='validate_ommers', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='chain', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='chain', ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + Assign( + targets=[ + Name(id='parent_has_ommers', ctx=Store())], + value=Compare( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='EMPTY_OMMER_HASH', ctx=Load())])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_difficulty', ctx=Store())], + value=Call( + func=Name(id='calculate_block_difficulty', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Name(id='parent_has_ommers', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_difficulty', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='validate_proof_of_work', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generate_header_hash_for_pow', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate rlp hash of the header which is to be used for Proof-of-Work\n verification.\n\n In other words, the PoW artefacts `mix_digest` and `nonce` are ignored\n while calculating this hash.\n\n A particular PoW is valid for a single hash, that hash is computed by\n this function. The `nonce` and `mix_digest` are omitted from this hash\n because they are being changed by miners in their search for a sufficient\n proof-of-work.\n\n Parameters\n ----------\n header :\n The header object for which the hash is to be generated.\n\n Returns\n -------\n hash : `Hash32`\n The PoW valid rlp hash of the passed in header.\n ')), + Assign( + targets=[ + Name(id='header_data_without_pow_artefacts', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='state_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='transactions_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='receipt_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='bloom', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='header_data_without_pow_artefacts', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='validate_proof_of_work', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the Proof of Work constraints.\n\n In order to verify that a miner's proof-of-work is valid for a block, a\n ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``\n hash function. The mix digest is a hash of the header and the nonce that\n is passed through and it confirms whether or not proof-of-work was done\n on the correct block. The result is the actual hash value of the block.\n\n Parameters\n ----------\n header :\n Header of interest.\n ")), + Assign( + targets=[ + Name(id='header_hash', ctx=Store())], + value=Call( + func=Name(id='generate_header_hash_for_pow', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache', ctx=Store())], + value=Call( + func=Name(id='generate_cache', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='mix_digest', ctx=Store()), + Name(id='result', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='hashimoto_light', ctx=Load()), + args=[ + Name(id='header_hash', ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + Name(id='cache', ctx=Load()), + Call( + func=Name(id='dataset_size', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='mix_digest', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='mix_digest', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='limit', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='limit', ctx=Load()), + op=FloorDiv(), + right=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n gas_available :\n The gas remaining in the block.\n chain_id :\n The ID of the current chain.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + Return( + value=Name(id='sender_address', ctx=Load()))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='error', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n error :\n Error in the top level frame of the transaction, if any.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='succeeded', + value=Compare( + left=Name(id='error', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)])), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + Return( + value=Name(id='receipt', ctx=Load()))], + decorator_list=[], + returns=Name(id='Receipt', ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='block_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n block_difficulty :\n Difficulty of the block.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='transactions', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='tx', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='gas_available', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='gas_price', + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='difficulty', + value=Name(id='block_difficulty', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='chain_id', + value=Name(id='chain_id', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store()), + Name(id='error', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='error', ctx=Load()), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='pay_rewards', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='block_number', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='ommers', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='validate_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='block_header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the ommers mentioned in the block.\n\n An ommer block is a block that wasn't canonically added to the\n blockchain because it wasn't validated as fast as the canonical block\n but was mined at the same time.\n\n To be considered valid, the ommers must adhere to the rules defined in\n the Ethereum protocol. The maximum amount of ommers is 2 per block and\n there cannot be duplicate ommers in a block. Many of the other ommer\n constraints are listed in the in-line comments of this function.\n\n Parameters\n ----------\n ommers :\n List of ommers mentioned in the current block.\n block_header:\n The header of current block.\n chain :\n History and current state.\n ")), + Assign( + targets=[ + Name(id='block_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='block_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='ommers_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return()], + orelse=[]), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + op=Sub(), + right=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Name(id='ommer', ctx=Load()), + Name(id='ommer_parent_header', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=2)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommers_hashes', ctx=Store())], + value=ListComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + ifs=[], + is_async=0)])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[])], + keywords=[])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_canonical_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=BinOp( + left=Name(id='MAX_OMMER_DEPTH', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + ctx=Load())), + Assign( + targets=[ + Name(id='recent_canonical_block_hashes', ctx=Store())], + value=SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='recent_ommers_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + simple=1), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='recent_ommers_hashes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='recent_ommers_hashes', ctx=Load()), + attr='union', + ctx=Load()), + args=[ + SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='ommer_index', ctx=Store()), + Name(id='ommer', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='ommer_hash', ctx=Store())], + value=Subscript( + value=Name(id='ommers_hashes', ctx=Load()), + slice=Name(id='ommer_index', ctx=Load()), + ctx=Load())), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='block_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_ommers_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='ommer_age', ctx=Load())]), + Compare( + left=Name(id='ommer_age', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_OMMER_DEPTH', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='parent_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pay_rewards', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pay rewards to the block miner as well as the ommers miners.\n\n The miner of the canonical block is rewarded with the predetermined\n block reward, ``BLOCK_REWARD``, plus a variable award based off of the\n number of ommer blocks that were mined around the same time, and included\n in the canonical block's header. An ommer block is a block that wasn't\n added to the canonical blockchain because it wasn't validated as fast as\n the accepted block but was mined at the same time. Although not all blocks\n that are mined are added to the canonical chain, miners are still paid a\n reward for their efforts. This reward is called an ommer reward and is\n calculated based on the number associated with the ommer block that they\n mined.\n\n Parameters\n ----------\n state :\n Current account state.\n block_number :\n Position of the block within the chain.\n coinbase :\n Address of account which receives block reward and transaction fees.\n ommers :\n List of ommers mentioned in the current block.\n ")), + Assign( + targets=[ + Name(id='ommer_count', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='miner_reward', ctx=Store())], + value=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='ommer_count', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='miner_reward', ctx=Load())], + keywords=[])), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_number', ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='ommer_miner_reward', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Sub(), + right=Name(id='ommer_age', ctx=Load())), + op=Mult(), + right=Name(id='BLOCK_REWARD', ctx=Load())), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='ommer_miner_reward', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + If( + test=Compare( + left=Name(id='coinbase_balance_after_mining_fee', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]))], + orelse=[])]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='error', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Name(id='TX_CREATE_COST', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='v', ctx=Store()), + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=28)])]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash_pre155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='chain_id_x2', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=36)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[])), + op=Sub(), + right=Name(id='chain_id_x2', ctx=Load())), + Call( + func=Name(id='signing_hash_155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])], + keywords=[]))]), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash_pre155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a legacy (pre EIP 155) signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 155 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n The id of the current chain.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='chain_id', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_has_ommers', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes difficulty of a block using its header and parent header.\n\n The difficulty is determined by the time the block was created after its\n parent. The ``offset`` is calculated using the parent block's difficulty,\n ``parent_difficulty``, and the timestamp between blocks. This offset is\n then added to the parent difficulty and is stored as the ``difficulty``\n variable. If the time between the block and its parent is too short, the\n offset will result in a positive number thus making the sum of\n ``parent_difficulty`` and ``offset`` to be a greater value in order to\n avoid mass forking. But, if the time is long enough, then the offset\n results in a negative value making the block less difficult than\n its parent.\n\n The base standard for a block's difficulty is the predefined value\n set for the genesis block since it has no parent. So, a block\n can't be less difficult than the genesis block, therefore each block's\n difficulty is set to the maximum value between the calculated\n difficulty and the ``GENESIS_DIFFICULTY``.\n\n Parameters\n ----------\n block_number :\n Block number of the block.\n block_timestamp :\n Timestamp of the block.\n parent_timestamp :\n Timestamp of the parent block.\n parent_difficulty :\n difficulty of the parent block.\n parent_has_ommers:\n does the parent have ommers.\n\n Returns\n -------\n difficulty : `ethereum.base_types.Uint`\n Computed difficulty for a block.\n ")), + Assign( + targets=[ + Name(id='offset', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=2048)), + op=Mult(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=IfExp( + test=Name(id='parent_has_ommers', ctx=Load()), + body=Constant(value=2), + orelse=Constant(value=1)), + op=Sub(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_timestamp', ctx=Load()), + op=Sub(), + right=Name(id='parent_timestamp', ctx=Load()))], + keywords=[]), + op=FloorDiv(), + right=Constant(value=9))), + UnaryOp( + op=USub(), + operand=Constant(value=99))], + keywords=[]))), + Assign( + targets=[ + Name(id='difficulty', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='offset', ctx=Load()))), + Assign( + targets=[ + Name(id='num_bomb_periods', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='BOMB_DELAY_BLOCKS', ctx=Load())), + op=FloorDiv(), + right=Constant(value=100000)), + op=Sub(), + right=Constant(value=2))), + If( + test=Compare( + left=Name(id='num_bomb_periods', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='difficulty', ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Name(id='num_bomb_periods', ctx=Load())))], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='difficulty', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/fork.v b/coq/ethereum/muir_glacier/fork.v new file mode 100644 index 0000000000..e7d31608a0 --- /dev/null +++ b/coq/ethereum/muir_glacier/fork.v @@ -0,0 +1,847 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.ethash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.muir_glacier.__init__. +Require ethereum.muir_glacier.blocks. +Require ethereum.muir_glacier.bloom. +Require ethereum.muir_glacier.fork_types. +Require ethereum.muir_glacier.state. +Require ethereum.muir_glacier.transactions. +Require ethereum.muir_glacier.trie. +Require ethereum.muir_glacier.utils.message. +Require ethereum.muir_glacier.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + do* [[ M.get_local ~(| "validate_ommers" |) ~(| + M.get_field ~(| block, "ommers" |), + M.get_field ~(| block, "header" |), + chain + |) ]] in + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "difficulty" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| block, "ommers" |), + M.get_field ~(| chain, "chain_id" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + do* M.assign "parent_has_ommers" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_difficulty" [[ + M.get_local ~(| "calculate_block_difficulty" |) ~(| + M.get_field ~(| header, "number" |), + M.get_field ~(| header, "timestamp" |), + M.get_field ~(| parent_header, "timestamp" |), + M.get_field ~(| parent_header, "difficulty" |), + M.get_local ~(| "parent_has_ommers" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| + header + |) ]] in + M.pure tt. + +Definition generate_header_hash_for_pow (header : Header) : M Hash32 := + (* + 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. + *) + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_proof_of_work (header : Header) : M unit := + (* + 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. + *) + do* M.assign "header_hash" [[ + M.get_local ~(| "generate_header_hash_for_pow" |) ~(| + header + |) in + ]] in + do* M.assign "cache" [[ + ethereum.ethash.generate_cache ~(| + M.get_field ~(| header, "number" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (gas_available : Uint) (chain_id : U64) : M Address := + (* + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (error : (* TODO type *)) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (block_gas_limit : Uint) (block_time : U256) (block_difficulty : Uint) (transactions : (* TODO type *)) (ommers : (* TODO type *)) (chain_id : U64) : M ApplyBodyOutput := + (* + 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.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "pay_rewards" |) ~(| + state, + block_number, + coinbase, + ommers + |) ]] in + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_ommers (ommers : (* TODO type *)) (block_header : Header) (chain : BlockChain) : M unit := + (* + 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. + *) + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_canonical_blocks" [[ + (* TODO expression *) in + ]] in + do* M.assign "recent_canonical_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition pay_rewards (state : State) (block_number : Uint) (coinbase : Address) (ommers : (* TODO type *)) : M unit := + (* + 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. + *) + do* M.assign "ommer_count" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + ommers + |) + |) in + ]] in + do* M.assign "miner_reward" [[ + (* TODO expression *) in + ]] in + do* [[ state.create_ether ~(| + state, + coinbase, + M.get_local ~(| "miner_reward" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + do* M.assign "gas_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_pre155 (tx : Transaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_155 (tx : Transaction) (chain_id : U64) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_block_difficulty (block_number : Uint) (block_timestamp : U256) (parent_timestamp : U256) (parent_difficulty : Uint) (parent_has_ommers : bool) : M Uint := + (* + 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. + *) + do* M.assign "offset" [[ + (* TODO expression *) in + ]] in + do* M.assign "difficulty" [[ + (* TODO expression *) in + ]] in + do* M.assign "num_bomb_periods" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/fork_types.ast b/coq/ethereum/muir_glacier/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/muir_glacier/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/fork_types.v b/coq/ethereum/muir_glacier/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/muir_glacier/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/state.ast b/coq/ethereum/muir_glacier/state.ast new file mode 100644 index 0000000000..c04909fdce --- /dev/null +++ b/coq/ethereum/muir_glacier/state.ast @@ -0,0 +1,1692 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='created_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='set', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mark_account_created', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Mark an account as having been created in the current transaction.\n This information is used by `get_storage_original()` to handle an obscure\n edgecase.\n\n The marker is not removed even if the account creation reverts. Since the\n account cannot have had code prior to its creation and can't call\n `get_storage_original()`, this is harmless.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account that has been created.\n ")), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has zero nonce, empty code and zero balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_empty : `bool`\n True if if an account has zero nonce, empty code and zero balance,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_exists_and_is_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists and has zero nonce, empty code and zero\n balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n exists_and_is_empty : `bool`\n True if an account exists and has zero nonce, empty code and zero\n balance, False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='account', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_alive', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether is an account is both in the state and non empty.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_alive : `bool`\n True if the account is alive.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[ + Return( + value=UnaryOp( + op=Not(), + operand=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])])))])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add newly created ether to an account.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to which ether is added.\n amount:\n The amount of ether to be added to the account of interest.\n ')), + FunctionDef( + name='increase_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage_original', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the original value in a storage slot i.e. the value before the current\n transaction began. This function reads the value from the snapshots taken\n before executing the transaction.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to read the value from.\n key:\n Key of the storage slot.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='_', ctx=Store()), + Name(id='original_trie', ctx=Store())], + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + Assign( + targets=[ + Name(id='original_account_trie', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='original_trie', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='original_account_trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='original_account_trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[]))]), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='original_value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='original_value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/state.v b/coq/ethereum/muir_glacier/state.v new file mode 100644 index 0000000000..a2887a7c0f --- /dev/null +++ b/coq/ethereum/muir_glacier/state.v @@ -0,0 +1,614 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.muir_glacier.fork_types. +Require ethereum.muir_glacier.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition mark_account_created (state : State) (address : Address) : M unit := + (* + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| + address + |) ]] in + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_empty (state : State) (address : Address) : M bool := + (* + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition account_exists_and_is_empty (state : State) (address : Address) : M bool := + (* + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_alive (state : State) (address : Address) : M bool := + (* + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := + (* + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. + +Definition get_storage_original (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + *) + (* TODO statement *) + (* TODO assignment *) + do* M.assign "original_account_trie" [[ + M.get_field ~(| M.get_local ~(| "original_trie" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/transactions.ast b/coq/ethereum/muir_glacier/transactions.ast new file mode 100644 index 0000000000..466c329804 --- /dev/null +++ b/coq/ethereum/muir_glacier/transactions.ast @@ -0,0 +1,106 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + ClassDef( + name='Transaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/transactions.v b/coq/ethereum/muir_glacier/transactions.v new file mode 100644 index 0000000000..9ea3014845 --- /dev/null +++ b/coq/ethereum/muir_glacier/transactions.v @@ -0,0 +1,13 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.muir_glacier.fork_types. diff --git a/coq/ethereum/muir_glacier/trie.ast b/coq/ethereum/muir_glacier/trie.ast new file mode 100644 index 0000000000..c9ca8c9c10 --- /dev/null +++ b/coq/ethereum/muir_glacier/trie.ast @@ -0,0 +1,1618 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.istanbul', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.RLP`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/trie.v b/coq/ethereum/muir_glacier/trie.v new file mode 100644 index 0000000000..6b8953f256 --- /dev/null +++ b/coq/ethereum/muir_glacier/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/utils/__init__.ast b/coq/ethereum/muir_glacier/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/muir_glacier/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/utils/__init__.v b/coq/ethereum/muir_glacier/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/muir_glacier/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/muir_glacier/utils/address.ast b/coq/ethereum/muir_glacier/utils/address.ast new file mode 100644 index 0000000000..03864d8b79 --- /dev/null +++ b/coq/ethereum/muir_glacier/utils/address.ast @@ -0,0 +1,216 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this muir_glacier version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_create2_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='salt', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='call_data', + annotation=Name(id='bytearray', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created, which is\n based on the sender address, salt and the call data as well.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n salt :\n Address generation salt.\n call_data :\n The code of the new account which is to be created.\n\n Returns\n -------\n address: `ethereum.muir_glacier.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='preimage', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Constant(value=b'\xff'), + op=Add(), + right=Name(id='address', ctx=Load())), + op=Add(), + right=Name(id='salt', ctx=Load())), + op=Add(), + right=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='call_data', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/utils/address.v b/coq/ethereum/muir_glacier/utils/address.v new file mode 100644 index 0000000000..160a725a3d --- /dev/null +++ b/coq/ethereum/muir_glacier/utils/address.v @@ -0,0 +1,115 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this muir_glacier version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.muir_glacier.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition compute_create2_contract_address (address : Address) (salt : Bytes32) (call_data : bytearray) : M Address := + (* + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.muir_glacier.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "preimage" [[ + (* TODO expression *) in + ]] in + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "preimage" |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/utils/hexadecimal.ast b/coq/ethereum/muir_glacier/utils/hexadecimal.ast new file mode 100644 index 0000000000..d82e7ac34d --- /dev/null +++ b/coq/ethereum/muir_glacier/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to\nMuir Glacier types.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/utils/hexadecimal.v b/coq/ethereum/muir_glacier/utils/hexadecimal.v new file mode 100644 index 0000000000..4a86da9538 --- /dev/null +++ b/coq/ethereum/muir_glacier/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Muir Glacier types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.muir_glacier.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/utils/message.ast b/coq/ethereum/muir_glacier/utils/message.ast new file mode 100644 index 0000000000..d401efffae --- /dev/null +++ b/coq/ethereum/muir_glacier/utils/message.ast @@ -0,0 +1,241 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this muir_glacier version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_static', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True), + Constant(value=False)]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n is_static:\n if True then it prevents all state-changing operations from being\n executed.\n\n Returns\n -------\n message: `ethereum.muir_glacier.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=Name(id='is_static', ctx=Load())), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/utils/message.v b/coq/ethereum/muir_glacier/utils/message.v new file mode 100644 index 0000000000..87df398f73 --- /dev/null +++ b/coq/ethereum/muir_glacier/utils/message.v @@ -0,0 +1,60 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this muir_glacier version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.muir_glacier.fork_types. +Require ethereum.muir_glacier.state. +Require ethereum.muir_glacier.vm. +Require ethereum.muir_glacier.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) (is_static : bool) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + + Returns + ------- + message: `ethereum.muir_glacier.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/__init__.ast b/coq/ethereum/muir_glacier/vm/__init__.ast new file mode 100644 index 0000000000..d2a1a3d8d7 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/__init__.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty')], + level=2), + ImportFrom( + module='precompiled_contracts', + names=[ + alias(name='RIPEMD160_ADDRESS')], + level=1), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='is_static', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='return_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + If( + test=Compare( + left=Name(id='RIPEMD160_ADDRESS', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/__init__.v b/coq/ethereum/muir_glacier/vm/__init__.v new file mode 100644 index 0000000000..16c9085cfa --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/__init__.v @@ -0,0 +1,72 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.muir_glacier.blocks. +Require ethereum.muir_glacier.fork_types. +Require ethereum.muir_glacier.state. +Require ethereum.muir_glacier.vm.precompiled_contracts. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "touched_accounts" |), "update" |) ~(| + M.get_field ~(| child_evm, "touched_accounts" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + (* TODO statement *) + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/exceptions.ast b/coq/ethereum/muir_glacier/vm/exceptions.ast new file mode 100644 index 0000000000..1a05416bbd --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/exceptions.ast @@ -0,0 +1,165 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='Revert', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised by the `REVERT` opcode.\n\n Unlike other EVM exceptions this does not result in the consumption of all\n gas.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='WriteInStaticContext', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt is made to modify the state while operating inside\n of a STATICCALL context.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfBoundsRead', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt was made to read data beyond the\n boundaries of the buffer.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidParameter', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when invalid parameters are passed.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/exceptions.v b/coq/ethereum/muir_glacier/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/muir_glacier/vm/gas.ast b/coq/ethereum/muir_glacier/vm/gas.ast new file mode 100644 index 0000000000..3268524e5e --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/gas.ast @@ -0,0 +1,833 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=800)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXTERNAL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BALANCE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='REFUND_SELF_DESTRUCT', ctx=Store())], + value=Constant(value=24000)), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RETURN_DATA_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_FAST_STEP', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLAKE2_PER_ROUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_left', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='memory_cost', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='extra_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='call_stipend', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Expr( + value=Constant(value='\n Calculates the MessageCallGas (cost and stipend) for\n executing call Opcodes.\n\n Parameters\n ----------\n value:\n The amount of `ETH` that needs to be transferred.\n gas :\n The amount of gas provided to the message-call.\n gas_left :\n The amount of gas left in the current frame.\n memory_cost :\n The amount needed to extend the memory in the current frame.\n extra_gas :\n The amount of gas needed for transferring value + creating a new\n account inside a message call.\n call_stipend :\n The amount of stipend provided to a message call to execute code while\n transferring value(ETH).\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='call_stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='call_stipend', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='extra_gas', ctx=Load()), + op=Add(), + right=Name(id='memory_cost', ctx=Load()))]), + body=[ + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='gas', ctx=Load()), + Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='gas_left', ctx=Load()), + op=Sub(), + right=Name(id='memory_cost', ctx=Load())), + op=Sub(), + right=Name(id='extra_gas', ctx=Load()))], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load())), + FunctionDef( + name='max_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the maximum gas that is allowed for making a message call\n\n Parameters\n ----------\n gas :\n The amount of gas provided to the message-call.\n\n Returns\n -------\n max_allowed_message_call_gas: `ethereum.base_types.Uint`\n The maximum gas allowed for making the message-call.\n ')), + Return( + value=BinOp( + left=Name(id='gas', ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='gas', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]))))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/gas.v b/coq/ethereum/muir_glacier/vm/gas.v new file mode 100644 index 0000000000..59522f596a --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/gas.v @@ -0,0 +1,171 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (value : U256) (gas : Uint) (gas_left : Uint) (memory_cost : Uint) (extra_gas : Uint) (call_stipend : Uint) : M MessageCallGas := + (* + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "gas" [[ + M.get_local ~(| "min" |) ~(| + gas, + M.get_local ~(| "max_message_call_gas" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition max_message_call_gas (gas : Uint) : M Uint := + (* + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/instructions/__init__.ast b/coq/ethereum/muir_glacier/vm/instructions/__init__.ast new file mode 100644 index 0000000000..4f4c60bb9b --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/__init__.ast @@ -0,0 +1,1780 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='SHL', ctx=Store())], + value=Constant(value=27)), + Assign( + targets=[ + Name(id='SHR', ctx=Store())], + value=Constant(value=28)), + Assign( + targets=[ + Name(id='SAR', ctx=Store())], + value=Constant(value=29)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='RETURNDATASIZE', ctx=Store())], + value=Constant(value=61)), + Assign( + targets=[ + Name(id='RETURNDATACOPY', ctx=Store())], + value=Constant(value=62)), + Assign( + targets=[ + Name(id='EXTCODEHASH', ctx=Store())], + value=Constant(value=63)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='DIFFICULTY', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='CHAINID', ctx=Store())], + value=Constant(value=70)), + Assign( + targets=[ + Name(id='SELFBALANCE', ctx=Store())], + value=Constant(value=71)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='CREATE2', ctx=Store())], + value=Constant(value=245)), + Assign( + targets=[ + Name(id='STATICCALL', ctx=Store())], + value=Constant(value=250)), + Assign( + targets=[ + Name(id='REVERT', ctx=Store())], + value=Constant(value=253)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SAR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIFFICULTY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CHAINID', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODEHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFBALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STATICCALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='REVERT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE2', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shl', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shr', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_sar', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodehash', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='self_balance', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='staticcall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='revert', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create2', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/instructions/__init__.v b/coq/ethereum/muir_glacier/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/muir_glacier/vm/instructions/arithmetic.ast b/coq/ethereum/muir_glacier/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/instructions/arithmetic.v b/coq/ethereum/muir_glacier/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..f912e92eaf --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/instructions/bitwise.ast b/coq/ethereum/muir_glacier/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..b72397f0ec --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/bitwise.ast @@ -0,0 +1,751 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shl', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift left (SHL) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='value', ctx=Load()), + op=LShift(), + right=Name(id='shift', ctx=Load())), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]))], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shr', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift right (SHR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_sar', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Arithmetic shift right (SAR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='signed_value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=256)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + BinOp( + left=Name(id='signed_value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load()))], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='signed_value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load()))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/instructions/bitwise.v b/coq/ethereum/muir_glacier/vm/instructions/bitwise.v new file mode 100644 index 0000000000..a82117cf12 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/bitwise.v @@ -0,0 +1,309 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shl (evm : Evm) : M unit := + (* + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shr (evm : Evm) : M unit := + (* + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_sar (evm : Evm) : M unit := + (* + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + M.get_local ~(| "int" |) ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "signed_value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/instructions/block.ast b/coq/ethereum/muir_glacier/vm/instructions/block.ast new file mode 100644 index 0000000000..b9ccb3290b --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/block.ast @@ -0,0 +1,492 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's difficulty onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='chain_id', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the chain id onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/instructions/block.v b/coq/ethereum/muir_glacier/vm/instructions/block.v new file mode 100644 index 0000000000..6814eb2a38 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/block.v @@ -0,0 +1,241 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition difficulty (evm : Evm) : M unit := + (* + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition chain_id (evm : Evm) : M unit := + (* + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/instructions/comparison.ast b/coq/ethereum/muir_glacier/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/instructions/comparison.v b/coq/ethereum/muir_glacier/vm/instructions/comparison.v new file mode 100644 index 0000000000..7085c25f4b --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/instructions/control_flow.ast b/coq/ethereum/muir_glacier/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/instructions/control_flow.v b/coq/ethereum/muir_glacier/vm/instructions/control_flow.v new file mode 100644 index 0000000000..2b26336f1f --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.exceptions. +Require ethereum.muir_glacier.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/instructions/environment.ast b/coq/ethereum/muir_glacier/vm/instructions/environment.ast new file mode 100644 index 0000000000..859f5acfff --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/environment.ast @@ -0,0 +1,1641 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfBoundsRead')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BALANCE'), + alias(name='GAS_BASE'), + alias(name='GAS_CODE_HASH'), + alias(name='GAS_COPY'), + alias(name='GAS_EXTERNAL'), + alias(name='GAS_FAST_STEP'), + alias(name='GAS_RETURN_DATA_COPY'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BALANCE', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_EXTERNAL', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_EXTERNAL', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the size of the return data buffer onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copies data from the return data buffer code to memory\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='return_data_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_RETURN_DATA_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='return_data_start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfBoundsRead', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load()), + slice=Slice( + lower=Name(id='return_data_start_position', ctx=Load()), + upper=BinOp( + left=Name(id='return_data_start_position', ctx=Load()), + op=Add(), + right=Name(id='size', ctx=Load()))), + ctx=Load())), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodehash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns the keccak256 hash of a contract’s bytecode\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_CODE_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='EMPTY_ACCOUNT', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codehash', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='self_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the current address to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_FAST_STEP', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/instructions/environment.v b/coq/ethereum/muir_glacier/vm/instructions/environment.v new file mode 100644 index 0000000000..a3eaac0f46 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/environment.v @@ -0,0 +1,712 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.muir_glacier.fork_types. +Require ethereum.muir_glacier.state. +Require ethereum.muir_glacier.utils.address. +Require ethereum.muir_glacier.vm.memory. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.exceptions. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BALANCE + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_EXTERNAL + |) ]] in + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatasize (evm : Evm) : M unit := + (* + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatacopy (evm : Evm) : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "return_data_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + (* TODO expression *) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodehash (evm : Evm) : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_CODE_HASH + |) ]] in + do* M.assign "account" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codehash" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition self_balance (evm : Evm) : M unit := + (* + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_FAST_STEP + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/instructions/keccak.ast b/coq/ethereum/muir_glacier/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/instructions/keccak.v b/coq/ethereum/muir_glacier/vm/instructions/keccak.v new file mode 100644 index 0000000000..e6d9aae163 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.memory. +Require ethereum.muir_glacier.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/instructions/log.ast b/coq/ethereum/muir_glacier/vm/instructions/log.ast new file mode 100644 index 0000000000..0ded0e04ba --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/log.ast @@ -0,0 +1,323 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/instructions/log.v b/coq/ethereum/muir_glacier/vm/instructions/log.v new file mode 100644 index 0000000000..92d3d9d180 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/log.v @@ -0,0 +1,79 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.muir_glacier.blocks. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.exceptions. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.memory. +Require ethereum.muir_glacier.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO statement *) + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/instructions/memory.ast b/coq/ethereum/muir_glacier/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/instructions/memory.v b/coq/ethereum/muir_glacier/vm/instructions/memory.v new file mode 100644 index 0000000000..da9feaf56a --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.memory. +Require ethereum.muir_glacier.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/instructions/stack.ast b/coq/ethereum/muir_glacier/vm/instructions/stack.ast new file mode 100644 index 0000000000..95cfc0b6cf --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/stack.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/instructions/stack.v b/coq/ethereum/muir_glacier/vm/instructions/stack.v new file mode 100644 index 0000000000..b2e2b644ff --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/stack.v @@ -0,0 +1,153 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.exceptions. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/instructions/storage.ast b/coq/ethereum/muir_glacier/vm/instructions/storage.ast new file mode 100644 index 0000000000..1930ab7b69 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/storage.ast @@ -0,0 +1,437 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='get_storage_original'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_STIPEND'), + alias(name='GAS_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_SLOAD', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='get_storage_original', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='current_value', ctx=Load())]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())])]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_UPDATE', ctx=Load()))])], + orelse=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SLOAD', ctx=Load()))]), + If( + test=Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='GAS_STORAGE_SET', ctx=Load()), + op=Sub(), + right=Name(id='GAS_SLOAD', ctx=Load()))], + keywords=[]))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_SLOAD', ctx=Load()))], + keywords=[]))])], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/instructions/storage.v b/coq/ethereum/muir_glacier/vm/instructions/storage.v new file mode 100644 index 0000000000..874f302440 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/storage.v @@ -0,0 +1,118 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.muir_glacier.state. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.exceptions. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_SLOAD + |) ]] in + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "original_value" [[ + state.get_storage_original ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/instructions/system.ast b/coq/ethereum/muir_glacier/vm/instructions/system.ast new file mode 100644 index 0000000000..6801ce9810 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/system.ast @@ -0,0 +1,2745 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='is_account_alive'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='compute_create2_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='Revert'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL'), + alias(name='GAS_CALL_VALUE'), + alias(name='GAS_CREATE'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='GAS_NEW_ACCOUNT'), + alias(name='GAS_SELF_DESTRUCT'), + alias(name='GAS_SELF_DESTRUCT_NEW_ACCOUNT'), + alias(name='GAS_ZERO'), + alias(name='REFUND_SELF_DESTRUCT'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas'), + alias(name='max_message_call_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='generic_create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='endowment', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='contract_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='memory_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Core logic used by the `CREATE*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='create_message_gas', ctx=Load())), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='is_static', + value=Constant(value=False)), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create2', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Creates a new account with associated code.\n\n It's similar to CREATE opcode except that the address of new account\n depends on the init_code instead of the nonce of sender.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ")), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='salt', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='call_data_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='call_data_words', ctx=Load()))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_create2_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='salt', ctx=Load()), + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_staticcall', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=IfExp( + test=Name(id='is_staticcall', ctx=Load()), + body=Constant(value=True), + orelse=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()))), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[])]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SELF_DESTRUCT', ctx=Load())), + If( + test=BoolOp( + op=And(), + values=[ + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[])), + Compare( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='refunded_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load())), + While( + test=Compare( + left=Name(id='parent_evm', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='refunded_accounts', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='originator', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='refunded_accounts', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Name(id='REFUND_SELF_DESTRUCT', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='GAS_CALL', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='staticcall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='GAS_CALL', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='revert', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop execution and revert state changes, without consuming all provided gas\n and also has the ability to return a reason\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Name(id='output', ctx=Load())], + keywords=[])), + Raise( + exc=Name(id='Revert', ctx=Load())), + Pass()], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/instructions/system.v b/coq/ethereum/muir_glacier/vm/instructions/system.v new file mode 100644 index 0000000000..e7edbce2ce --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/instructions/system.v @@ -0,0 +1,779 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.muir_glacier.fork_types. +Require ethereum.muir_glacier.state. +Require ethereum.muir_glacier.utils.address. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.exceptions. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.memory. +Require ethereum.muir_glacier.vm.stack. + +Definition generic_create (evm : Evm) (endowment : U256) (contract_address : Address) (memory_start_position : U256) (memory_size : U256) : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* M.assign "create_message_gas" [[ + gas.max_message_call_gas ~(| + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) in + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_local ~(| "create_message_gas" |) + ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_start_position, + memory_size + |) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_create_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition create2 (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "salt" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "call_data_words" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_create2_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "salt" |), + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (is_staticcall : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_SELF_DESTRUCT in + ]] in + (* TODO statement *) + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "refunded_accounts" [[ + M.get_field ~(| evm, "accounts_to_delete" |) in + ]] in + do* M.assign "parent_evm" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "parent_evm" |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + gas.GAS_CALL + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition staticcall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + gas.GAS_CALL + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "to" |), + M.get_local ~(| "to" |), + True, + True, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition revert (evm : Evm) : M unit := + (* + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "output" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/interpreter.ast b/coq/ethereum/muir_glacier/vm/interpreter.ast new file mode 100644 index 0000000000..12c8478b84 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/interpreter.ast @@ -0,0 +1,1137 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Iterable'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='increment_nonce'), + alias(name='mark_account_created'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidOpcode'), + alias(name='OutOfGasError'), + alias(name='Revert'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_CODE_SIZE', ctx=Store())], + value=Constant(value=24576)), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `touched_accounts`: Accounts that have been touched.\n 6. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='touched_accounts', + value=Name(id='touched_accounts', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.muir_glacier.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='mark_account_created', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_CODE_SIZE', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.muir_glacier.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='touched_accounts', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='return_data', + value=Constant(value=b'')), + keyword( + arg='error', + value=Constant(value=None))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))]), + ExceptHandler( + type=Name(id='Revert', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/interpreter.v b/coq/ethereum/muir_glacier/vm/interpreter.v new file mode 100644 index 0000000000..8813c774e6 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/interpreter.v @@ -0,0 +1,173 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.muir_glacier.blocks. +Require ethereum.muir_glacier.fork_types. +Require ethereum.muir_glacier.state. +Require ethereum.muir_glacier.vm. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.precompiled_contracts.mapping. +Require ethereum.muir_glacier.vm.__init__. +Require ethereum.muir_glacier.vm.exceptions. +Require ethereum.muir_glacier.vm.instructions. +Require ethereum.muir_glacier.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.muir_glacier.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.mark_account_created ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.muir_glacier.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/memory.ast b/coq/ethereum/muir_glacier/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/memory.v b/coq/ethereum/muir_glacier/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/__init__.ast b/coq/ethereum/muir_glacier/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..bb9991907f --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS'), + Constant(value='MODEXP_ADDRESS'), + Constant(value='ALT_BN128_ADD_ADDRESS'), + Constant(value='ALT_BN128_MUL_ADDRESS'), + Constant(value='ALT_BN128_PAIRING_CHECK_ADDRESS'), + Constant(value='BLAKE2F_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[])), + Assign( + targets=[ + Name(id='MODEXP_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x05')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x06')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x07')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x08')], + keywords=[])), + Assign( + targets=[ + Name(id='BLAKE2F_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x09')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/__init__.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..1e500955af --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.muir_glacier.utils.hexadecimal. diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.ast b/coq/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.ast new file mode 100644 index 0000000000..f6f077419c --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.ast @@ -0,0 +1,913 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ALT_BN128 CONTRACTS\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ALT_BN128 precompiled contracts.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.alt_bn128', + names=[ + alias(name='ALT_BN128_CURVE_ORDER'), + alias(name='ALT_BN128_PRIME'), + alias(name='BNF'), + alias(name='BNF2'), + alias(name='BNF12'), + alias(name='BNP'), + alias(name='BNP2'), + alias(name='pairing')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=2), + FunctionDef( + name='alt_bn128_add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 addition precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=150)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load()), + Name(id='x1_value', ctx=Load()), + Name(id='y1_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='p1', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x1_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y1_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=BinOp( + left=Name(id='p0', ctx=Load()), + op=Add(), + right=Name(id='p1', ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 multiplication precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6000)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='n', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='p0', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='n', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_pairing_check', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 pairing check precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=34000), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))), + op=Add(), + right=Constant(value=45000))], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=192)), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='values', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=Name(id='j', ctx=Load()))), + upper=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=BinOp( + left=Name(id='j', ctx=Load()), + op=Add(), + right=Constant(value=1))))), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='values', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=Call( + func=Name(id='BNP2', ctx=Load()), + args=[ + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=3), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=2), + ctx=Load())], + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=5), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=4), + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='OutOfGasError', ctx=Load()), + args=[], + keywords=[]))])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='p', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='q', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='p', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + Compare( + left=Name(id='q', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='result', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='pairing', ctx=Load()), + args=[ + Name(id='q', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[])))], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='result', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000000..6c9beed797 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,226 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.alt_bn128. +Require ethereum.muir_glacier.vm. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.memory. +Require ethereum.muir_glacier.vm.exceptions. + +Definition alt_bn128_add (evm : Evm) : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 150 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "x1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x1_bytes" |) + |) + |) in + ]] in + do* M.assign "y1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y1_bytes" |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + (* TODO expression *) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_mul (evm : Evm) : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 6000 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "n" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + M.get_field ~(| M.get_local ~(| "p0" |), "mul_by" |) ~(| + M.get_local ~(| "n" |) + |) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_pairing_check (evm : Evm) : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + (* TODO expression *) + |) + |) ]] in + (* TODO statement *) + do* M.assign "result" [[ + M.get_field ~(| ethereum.crypto.alt_bn128.BNF12, "from_int" |) ~(| + 1 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.ast b/coq/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.ast new file mode 100644 index 0000000000..03747962f0 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.ast @@ -0,0 +1,137 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `Blake2` precompiled contract.\n')), + ImportFrom( + module='ethereum.crypto.blake2', + names=[ + alias(name='Blake2b')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BLAKE2_PER_ROUND'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidParameter')], + level=2), + FunctionDef( + name='blake2f', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the Blake2 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Constant(value=213)]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='blake2b', ctx=Store())], + value=Call( + func=Name(id='Blake2b', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='rounds', ctx=Store()), + Name(id='h', ctx=Store()), + Name(id='m', ctx=Store()), + Name(id='t_0', ctx=Store()), + Name(id='t_1', ctx=Store()), + Name(id='f', ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='get_blake2_parameters', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_BLAKE2_PER_ROUND', ctx=Load()), + op=Mult(), + right=Name(id='rounds', ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=Name(id='f', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + List( + elts=[ + Constant(value=0), + Constant(value=1)], + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='compress', + ctx=Load()), + args=[ + Name(id='rounds', ctx=Load()), + Name(id='h', ctx=Load()), + Name(id='m', ctx=Load()), + Name(id='t_0', ctx=Load()), + Name(id='t_1', ctx=Load()), + Name(id='f', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000000..60142ab7ac --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,46 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +*) + +Require ethereum.crypto.blake2. +Require ethereum.muir_glacier.vm. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.exceptions. + +Definition blake2f (evm : Evm) : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + (* TODO statement *) + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| + + |) in + ]] in + (* TODO assignment *) + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..353937db20 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.muir_glacier.vm. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/identity.ast b/coq/ethereum/muir_glacier/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/identity.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..0b836f14de --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.muir_glacier.vm. +Require ethereum.muir_glacier.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/mapping.ast b/coq/ethereum/muir_glacier/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..cec40e5736 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ALT_BN128_ADD_ADDRESS'), + alias(name='ALT_BN128_MUL_ADDRESS'), + alias(name='ALT_BN128_PAIRING_CHECK_ADDRESS'), + alias(name='BLAKE2F_ADDRESS'), + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='MODEXP_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='alt_bn128', + names=[ + alias(name='alt_bn128_add'), + alias(name='alt_bn128_mul'), + alias(name='alt_bn128_pairing_check')], + level=1), + ImportFrom( + module='blake2f', + names=[ + alias(name='blake2f')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='modexp', + names=[ + alias(name='modexp')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load()), + Name(id='MODEXP_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Load()), + Name(id='BLAKE2F_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load()), + Name(id='modexp', ctx=Load()), + Name(id='alt_bn128_add', ctx=Load()), + Name(id='alt_bn128_mul', ctx=Load()), + Name(id='alt_bn128_pairing_check', ctx=Load()), + Name(id='blake2f', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/mapping.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..c6c9c9920b --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/mapping.v @@ -0,0 +1,25 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.muir_glacier.fork_types. +Require ethereum.muir_glacier.vm.precompiled_contracts.__init__. +Require ethereum.muir_glacier.vm.precompiled_contracts.alt_bn128. +Require ethereum.muir_glacier.vm.precompiled_contracts.blake2f. +Require ethereum.muir_glacier.vm.precompiled_contracts.ecrecover. +Require ethereum.muir_glacier.vm.precompiled_contracts.identity. +Require ethereum.muir_glacier.vm.precompiled_contracts.modexp. +Require ethereum.muir_glacier.vm.precompiled_contracts.ripemd160. +Require ethereum.muir_glacier.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/modexp.ast b/coq/ethereum/muir_glacier/vm/precompiled_contracts/modexp.ast new file mode 100644 index 0000000000..010c07fd00 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/modexp.ast @@ -0,0 +1,631 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `MODEXP` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + Assign( + targets=[ + Name(id='GQUADDIVISOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + FunctionDef( + name='modexp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and.\n `modulus`. The return value is the same length as the modulus.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='base_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_start', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Add(), + right=Name(id='base_length', ctx=Load()))), + Assign( + targets=[ + Name(id='exp_head', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Call( + func=Name(id='min', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='gas_cost', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load()), + Name(id='exp_length', ctx=Load()), + Name(id='exp_head', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='base_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='modulus_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Name(id='base_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_start', ctx=Store())], + value=BinOp( + left=Name(id='exp_start', ctx=Load()), + op=Add(), + right=Name(id='exp_length', ctx=Load()))), + Assign( + targets=[ + Name(id='modulus', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='modulus_start', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='modulus', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'\x00')], + keywords=[]), + op=Mult(), + right=Name(id='modulus_length', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exp', ctx=Load()), + Name(id='modulus', ctx=Load())], + keywords=[]), + attr='to_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[]), + Constant(value='big')], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='complexity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Estimate the complexity of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n Returns\n -------\n\n complexity : `Uint`\n Complexity of performing the operation.\n ')), + Assign( + targets=[ + Name(id='max_length', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load())], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='max_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[])]), + body=[ + Return( + value=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='max_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])]), + body=[ + Return( + value=BinOp( + left=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=4)], + keywords=[])), + op=Add(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Mult(), + right=Name(id='max_length', ctx=Load()))), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3072)], + keywords=[])))], + orelse=[ + Return( + value=BinOp( + left=BinOp( + left=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[])), + op=Add(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=480)], + keywords=[]), + op=Mult(), + right=Name(id='max_length', ctx=Load()))), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=199680)], + keywords=[])))])])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='iterations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the number of iterations required to perform a modular\n exponentiation.\n\n Parameters\n ----------\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n iterations : `Uint`\n Number of iterations.\n ')), + If( + test=Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='adjusted_exp_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Constant(value=0), + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + op=Sub(), + right=Constant(value=1))], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='adjusted_exp_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=8), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=32))), + op=Add(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + Constant(value=0), + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + op=Sub(), + right=Constant(value=1))], + keywords=[]))], + keywords=[]))]), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='adjusted_exp_length', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the gas cost of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n gas_cost : `Uint`\n Gas required for performing the operation.\n ')), + Assign( + targets=[ + Name(id='multiplication_complexity', ctx=Store())], + value=Call( + func=Name(id='complexity', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='iteration_count', ctx=Store())], + value=Call( + func=Name(id='iterations', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load()), + Name(id='exponent_head', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cost', ctx=Store())], + value=BinOp( + left=Name(id='multiplication_complexity', ctx=Load()), + op=Mult(), + right=Name(id='iteration_count', ctx=Load()))), + AugAssign( + target=Name(id='cost', ctx=Store()), + op=FloorDiv(), + value=Name(id='GQUADDIVISOR', ctx=Load())), + Return( + value=Name(id='cost', ctx=Load()))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/modexp.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000000..b239242ee1 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/modexp.v @@ -0,0 +1,233 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.muir_glacier.vm. +Require ethereum.muir_glacier.vm.gas. +Require ethereum.muir_glacier.vm.memory. + +Definition modexp (evm : Evm) : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "base_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "modulus_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "exp_head" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "min" |) ~(| + ethereum_types.numeric.U256 ~(| + 32 + |), + M.get_local ~(| "exp_length" |) + |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) ~(| + M.get_local ~(| "base_length" |), + M.get_local ~(| "modulus_length" |), + M.get_local ~(| "exp_length" |), + M.get_local ~(| "exp_head" |) + |) + |) ]] in + (* TODO statement *) + do* M.assign "base" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + M.get_local ~(| "base_length" |) + |) + |) in + ]] in + do* M.assign "exp" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "exp_length" |) + |) + |) in + ]] in + do* M.assign "modulus_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "modulus" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "modulus_start" |), + M.get_local ~(| "modulus_length" |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := + (* + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + *) + do* M.assign "max_length" [[ + M.get_local ~(| "max" |) ~(| + ethereum_types.numeric.Uint ~(| + base_length + |), + ethereum_types.numeric.Uint ~(| + modulus_length + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition gas_cost (base_length : U256) (modulus_length : U256) (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + *) + do* M.assign "multiplication_complexity" [[ + M.get_local ~(| "complexity" |) ~(| + base_length, + modulus_length + |) in + ]] in + do* M.assign "iteration_count" [[ + M.get_local ~(| "iterations" |) ~(| + exponent_length, + exponent_head + |) in + ]] in + do* M.assign "cost" [[ + (* TODO expression *) in + ]] in + do* M.aug_assign [[ M.get_local ~(| "cost" |) ]] [[ + M.get_local ~(| "GQUADDIVISOR" |) + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/sha256.ast b/coq/ethereum/muir_glacier/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/precompiled_contracts/sha256.v b/coq/ethereum/muir_glacier/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/runtime.ast b/coq/ethereum/muir_glacier/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/runtime.v b/coq/ethereum/muir_glacier/vm/runtime.v new file mode 100644 index 0000000000..3f6795dea4 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.muir_glacier.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/muir_glacier/vm/stack.ast b/coq/ethereum/muir_glacier/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/muir_glacier/vm/stack.v b/coq/ethereum/muir_glacier/vm/stack.v new file mode 100644 index 0000000000..09bf3b8bc4 --- /dev/null +++ b/coq/ethereum/muir_glacier/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.muir_glacier.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/__init__.ast b/coq/ethereum/paris/__init__.ast new file mode 100644 index 0000000000..fe71ac1fae --- /dev/null +++ b/coq/ethereum/paris/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe Paris fork transitions Ethereum from a proof-of-work consensus model to a\nproof-of-stake one. This fork is often referred to as "The Merge" because it\nmarks the integration of the [consensus layer] with the execution layer\n(defined in this project.)\n\n[consensus layer]: https://github.com/ethereum/consensus-specs\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=15537394)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/__init__.v b/coq/ethereum/paris/__init__.v new file mode 100644 index 0000000000..46293983bf --- /dev/null +++ b/coq/ethereum/paris/__init__.v @@ -0,0 +1,11 @@ +(* Generated *) +(* +The Paris fork transitions Ethereum from a proof-of-work consensus model to a +proof-of-stake one. This fork is often referred to as "The Merge" because it +marks the integration of the [consensus layer] with the execution layer +(defined in this project.) + +[consensus layer]: https://github.com/ethereum/consensus-specs +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/paris/blocks.ast b/coq/ethereum/paris/blocks.ast new file mode 100644 index 0000000000..e3a1c6ccf8 --- /dev/null +++ b/coq/ethereum/paris/blocks.ast @@ -0,0 +1,230 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='LegacyTransaction')], + level=1), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='prev_randao', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='succeeded', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/blocks.v b/coq/ethereum/paris/blocks.v new file mode 100644 index 0000000000..6dc8830028 --- /dev/null +++ b/coq/ethereum/paris/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.paris.fork_types. +Require ethereum.paris.transactions. diff --git a/coq/ethereum/paris/bloom.ast b/coq/ethereum/paris/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/paris/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/bloom.v b/coq/ethereum/paris/bloom.v new file mode 100644 index 0000000000..c7eb535ef5 --- /dev/null +++ b/coq/ethereum/paris/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.paris.blocks. +Require ethereum.paris.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/exceptions.ast b/coq/ethereum/paris/exceptions.ast new file mode 100644 index 0000000000..a61ee25448 --- /dev/null +++ b/coq/ethereum/paris/exceptions.ast @@ -0,0 +1,72 @@ +Module( + body=[ + Expr( + value=Constant(value='\nExceptions specific to this fork.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Final')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidTransaction')], + level=0), + ClassDef( + name='TransactionTypeError', + bases=[ + Name(id='InvalidTransaction', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Unknown [EIP-2718] transaction type byte.\n\n [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718\n ')), + AnnAssign( + target=Name(id='transaction_type', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n The type byte of the transaction that caused the error.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='transaction_type', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='unknown transaction type `'), + FormattedValue( + value=Name(id='transaction_type', ctx=Load()), + conversion=-1), + Constant(value='`')])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='transaction_type', + ctx=Store())], + value=Name(id='transaction_type', ctx=Load()))], + decorator_list=[])], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/exceptions.v b/coq/ethereum/paris/exceptions.v new file mode 100644 index 0000000000..9a313f6d0e --- /dev/null +++ b/coq/ethereum/paris/exceptions.v @@ -0,0 +1,7 @@ +(* Generated *) +(* +Exceptions specific to this fork. +*) + +Require typing. +Require ethereum.exceptions. diff --git a/coq/ethereum/paris/fork.ast b/coq/ethereum/paris/fork.ast new file mode 100644 index 0000000000..cfc56cee03 --- /dev/null +++ b/coq/ethereum/paris/fork.ast @@ -0,0 +1,3032 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_ACCESS_LIST_ADDRESS_COST'), + alias(name='TX_ACCESS_LIST_STORAGE_KEY_COST'), + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='AccessListTransaction'), + alias(name='FeeMarketTransaction'), + alias(name='LegacyTransaction'), + alias(name='Transaction'), + alias(name='decode_transaction'), + alias(name='encode_transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='ELASTICITY_MULTIPLIER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='EMPTY_OMMER_HASH', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List(elts=[], ctx=Load())], + keywords=[])], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Tuple(elts=[], ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='prev_randao', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='chain', ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_base_fee_per_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the base fee per gas for the block.\n\n Parameters\n ----------\n block_gas_limit :\n Gas limit of the block for which the base fee is being calculated.\n parent_gas_limit :\n Gas limit of the parent block.\n parent_gas_used :\n Gas used in the parent block.\n parent_base_fee_per_gas :\n Base fee per gas of the parent block.\n\n Returns\n -------\n base_fee_per_gas : `Uint`\n Base fee per gas for the block.\n ')), + Assign( + targets=[ + Name(id='parent_gas_target', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='ELASTICITY_MULTIPLIER', ctx=Load()))), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Name(id='block_gas_limit', ctx=Load()), + Name(id='parent_gas_limit', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='parent_gas_used', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='parent_gas_target', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=Name(id='parent_base_fee_per_gas', ctx=Load()))], + orelse=[ + If( + test=Compare( + left=Name(id='parent_gas_used', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='parent_gas_target', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='gas_used_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_used', ctx=Load()), + op=Sub(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='parent_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Mult(), + right=Name(id='gas_used_delta', ctx=Load()))), + Assign( + targets=[ + Name(id='target_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='base_fee_per_gas_delta', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=Name(id='target_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Load())), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Add(), + right=Name(id='base_fee_per_gas_delta', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='gas_used_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_target', ctx=Load()), + op=Sub(), + right=Name(id='parent_gas_used', ctx=Load()))), + Assign( + targets=[ + Name(id='parent_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Mult(), + right=Name(id='gas_used_delta', ctx=Load()))), + Assign( + targets=[ + Name(id='target_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='base_fee_per_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='target_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Load()))), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Sub(), + right=Name(id='base_fee_per_gas_delta', ctx=Load())))])]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='expected_base_fee_per_gas', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_base_fee_per_gas', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='expected_base_fee_per_gas', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'\x00\x00\x00\x00\x00\x00\x00\x00')]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='EMPTY_OMMER_HASH', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n base_fee_per_gas :\n The block base fee.\n gas_available :\n The gas remaining in the block.\n chain_id :\n The ID of the current chain.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n effective_gas_price :\n The price to charge for gas when the transaction is executed.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='base_fee_per_gas', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='priority_fee_per_gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + op=Sub(), + right=Name(id='base_fee_per_gas', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='effective_gas_price', ctx=Store())], + value=BinOp( + left=Name(id='priority_fee_per_gas', ctx=Load()), + op=Add(), + right=Name(id='base_fee_per_gas', ctx=Load())))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='base_fee_per_gas', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='effective_gas_price', ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))]), + Return( + value=Tuple( + elts=[ + Name(id='sender_address', ctx=Load()), + Name(id='effective_gas_price', ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='error', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n error :\n The error from the execution if any.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='succeeded', + value=Compare( + left=Name(id='error', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)])), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='receipt', ctx=Load())], + keywords=[])))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='receipt', ctx=Load())], + keywords=[])))], + orelse=[ + Return( + value=Name(id='receipt', ctx=Load()))])])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Receipt', ctx=Load())], + ctx=Load()), + ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='prev_randao', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n base_fee_per_gas :\n Base fee per gas of within the block.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n prev_randao :\n The previous randao from the beacon chain.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Receipt', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Call( + func=Name(id='map', ctx=Load()), + args=[ + Name(id='decode_transaction', ctx=Load()), + Name(id='transactions', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Call( + func=Name(id='encode_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='sender_address', ctx=Store()), + Name(id='effective_gas_price', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='base_fee_per_gas', ctx=Load()), + Name(id='gas_available', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='base_fee_per_gas', + value=Name(id='base_fee_per_gas', ctx=Load())), + keyword( + arg='gas_price', + value=Name(id='effective_gas_price', ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='prev_randao', + value=Name(id='prev_randao', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='chain_id', + value=Name(id='chain_id', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store()), + Name(id='error', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='error', ctx=Load()), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='max_gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='max_gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())))]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='max_gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='effective_gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='effective_gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='preaccessed_addresses', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='preaccessed_storage_keys', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Tuple( + elts=[ + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='address', ctx=Store()), + Name(id='keys', ctx=Store())], + ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='keys', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_storage_keys', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Name(id='address', ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[ + keyword( + arg='preaccessed_addresses', + value=Call( + func=Name(id='frozenset', ctx=Load()), + args=[ + Name(id='preaccessed_addresses', ctx=Load())], + keywords=[])), + keyword( + arg='preaccessed_storage_keys', + value=Call( + func=Name(id='frozenset', ctx=Load()), + args=[ + Name(id='preaccessed_storage_keys', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='priority_fee_per_gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Name(id='priority_fee_per_gas', ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + If( + test=Compare( + left=Name(id='coinbase_balance_after_mining_fee', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]))], + orelse=[])]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='error', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Name(id='TX_CREATE_COST', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Assign( + targets=[ + Name(id='access_list_cost', ctx=Store())], + value=Constant(value=0)), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Tuple( + elts=[ + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='_address', ctx=Store()), + Name(id='keys', ctx=Store())], + ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + body=[ + AugAssign( + target=Name(id='access_list_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_ACCESS_LIST_ADDRESS_COST', ctx=Load())), + AugAssign( + target=Name(id='access_list_cost', ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='keys', ctx=Load())], + keywords=[]), + op=Mult(), + right=Name(id='TX_ACCESS_LIST_STORAGE_KEY_COST', ctx=Load())))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load())), + op=Add(), + right=Name(id='access_list_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=28)])]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash_pre155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='chain_id_x2', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=36)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[])), + op=Sub(), + right=Name(id='chain_id_x2', ctx=Load())), + Call( + func=Name(id='signing_hash_155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])], + keywords=[]))])], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='y_parity', + ctx=Load()), + Call( + func=Name(id='signing_hash_2930', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='y_parity', + ctx=Load()), + Call( + func=Name(id='signing_hash_1559', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])])]), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash_pre155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='LegacyTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a legacy (pre EIP 155) signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='LegacyTransaction', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 155 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n The id of the current chain.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='chain_id', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_2930', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='AccessListTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 2930 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load())], + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_1559', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='FeeMarketTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 1559 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load())], + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/fork.v b/coq/ethereum/paris/fork.v new file mode 100644 index 0000000000..e1bd556532 --- /dev/null +++ b/coq/ethereum/paris/fork.v @@ -0,0 +1,716 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.paris.__init__. +Require ethereum.paris.blocks. +Require ethereum.paris.bloom. +Require ethereum.paris.fork_types. +Require ethereum.paris.state. +Require ethereum.paris.transactions. +Require ethereum.paris.trie. +Require ethereum.paris.utils.message. +Require ethereum.paris.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + (* TODO statement *) + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "base_fee_per_gas" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "prev_randao" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| chain, "chain_id" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_base_fee_per_gas (block_gas_limit : Uint) (parent_gas_limit : Uint) (parent_gas_used : Uint) (parent_base_fee_per_gas : Uint) : M Uint := + (* + 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. + *) + do* M.assign "parent_gas_target" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + (* TODO statement *) + do* M.assign "expected_base_fee_per_gas" [[ + M.get_local ~(| "calculate_base_fee_per_gas" |) ~(| + M.get_field ~(| header, "gas_limit" |), + M.get_field ~(| parent_header, "gas_limit" |), + M.get_field ~(| parent_header, "gas_used" |), + M.get_field ~(| parent_header, "base_fee_per_gas" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (base_fee_per_gas : Uint) (gas_available : Uint) (chain_id : U64) : M (* TODO type *) := + (* + 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. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (error : (* TODO type *)) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M (* TODO type *) := + (* + Make the receipt for a transaction that was executed. + + Parameters + ---------- + tx : + The executed transaction. + error : + The error from the execution if any. + cumulative_gas_used : + The total gas used so far in the block after the transaction was + executed. + logs : + The logs produced by the transaction. + + Returns + ------- + receipt : + The receipt for the transaction. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (base_fee_per_gas : Uint) (block_gas_limit : Uint) (block_time : U256) (prev_randao : Bytes32) (transactions : (* TODO type *)) (chain_id : U64) : M ApplyBodyOutput := + (* + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + prev_randao : + The previous randao from the beacon chain. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "effective_gas_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "preaccessed_addresses" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "preaccessed_storage_keys" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + (* TODO statement *) + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "priority_fee_per_gas" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "access_list_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_pre155 (tx : LegacyTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_155 (tx : LegacyTransaction) (chain_id : U64) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_2930 (tx : AccessListTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_1559 (tx : FeeMarketTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/fork_types.ast b/coq/ethereum/paris/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/paris/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/fork_types.v b/coq/ethereum/paris/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/paris/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/state.ast b/coq/ethereum/paris/state.ast new file mode 100644 index 0000000000..81c5372737 --- /dev/null +++ b/coq/ethereum/paris/state.ast @@ -0,0 +1,1641 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='created_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='set', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mark_account_created', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Mark an account as having been created in the current transaction.\n This information is used by `get_storage_original()` to handle an obscure\n edgecase.\n\n The marker is not removed even if the account creation reverts. Since the\n account cannot have had code prior to its creation and can't call\n `get_storage_original()`, this is harmless.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account that has been created.\n ")), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has zero nonce, empty code and zero balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_empty : `bool`\n True if if an account has zero nonce, empty code and zero balance,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_exists_and_is_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists and has zero nonce, empty code and zero\n balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n exists_and_is_empty : `bool`\n True if an account exists and has zero nonce, empty code and zero\n balance, False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='account', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_alive', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether is an account is both in the state and non empty.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_alive : `bool`\n True if the account is alive.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[ + Return( + value=UnaryOp( + op=Not(), + operand=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])])))])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage_original', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the original value in a storage slot i.e. the value before the current\n transaction began. This function reads the value from the snapshots taken\n before executing the transaction.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to read the value from.\n key:\n Key of the storage slot.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='_', ctx=Store()), + Name(id='original_trie', ctx=Store())], + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + Assign( + targets=[ + Name(id='original_account_trie', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='original_trie', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='original_account_trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='original_account_trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[]))]), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='original_value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='original_value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/state.v b/coq/ethereum/paris/state.v new file mode 100644 index 0000000000..723275d350 --- /dev/null +++ b/coq/ethereum/paris/state.v @@ -0,0 +1,593 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.paris.fork_types. +Require ethereum.paris.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition mark_account_created (state : State) (address : Address) : M unit := + (* + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| + address + |) ]] in + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_empty (state : State) (address : Address) : M bool := + (* + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition account_exists_and_is_empty (state : State) (address : Address) : M bool := + (* + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_alive (state : State) (address : Address) : M bool := + (* + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition get_storage_original (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + *) + (* TODO statement *) + (* TODO assignment *) + do* M.assign "original_account_trie" [[ + M.get_field ~(| M.get_local ~(| "original_trie" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/transactions.ast b/coq/ethereum/paris/transactions.ast new file mode 100644 index 0000000000..264b048f3f --- /dev/null +++ b/coq/ethereum/paris/transactions.ast @@ -0,0 +1,492 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='TransactionTypeError')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + Assign( + targets=[ + Name(id='TX_ACCESS_LIST_ADDRESS_COST', ctx=Store())], + value=Constant(value=2400)), + Assign( + targets=[ + Name(id='TX_ACCESS_LIST_STORAGE_KEY_COST', ctx=Store())], + value=Constant(value=1900)), + ClassDef( + name='LegacyTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='AccessListTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The transaction type added in EIP-2930 to support access lists.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='access_list', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y_parity', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='FeeMarketTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The transaction type added in EIP-1559.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_priority_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='access_list', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y_parity', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='Transaction', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Encode a transaction. Needed because non-legacy transactions aren't RLP.\n ")), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='tx', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])))], + orelse=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Unable to encode transaction of type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + conversion=-1)])], + keywords=[]))])])])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='decode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Decode a transaction. Needed because non-legacy transactions aren't RLP.\n ")), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Name(id='AccessListTransaction', ctx=Load()), + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=2)]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Name(id='FeeMarketTransaction', ctx=Load()), + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())], + keywords=[]))], + orelse=[ + Raise( + exc=Call( + func=Name(id='TransactionTypeError', ctx=Load()), + args=[ + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]))])])], + orelse=[ + Return( + value=Name(id='tx', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Transaction', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/transactions.v b/coq/ethereum/paris/transactions.v new file mode 100644 index 0000000000..1dee19f5cc --- /dev/null +++ b/coq/ethereum/paris/transactions.v @@ -0,0 +1,29 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.paris.exceptions. +Require ethereum.paris.fork_types. + +Definition encode_transaction (tx : Transaction) : M (* TODO type *) := + (* + Encode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + M.pure tt. + +Definition decode_transaction (tx : (* TODO type *)) : M Transaction := + (* + Decode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/trie.ast b/coq/ethereum/paris/trie.ast new file mode 100644 index 0000000000..de3e276fd9 --- /dev/null +++ b/coq/ethereum/paris/trie.ast @@ -0,0 +1,1632 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.gray_glacier', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='LegacyTransaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Receipt', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.RLP`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/trie.v b/coq/ethereum/paris/trie.v new file mode 100644 index 0000000000..6b8953f256 --- /dev/null +++ b/coq/ethereum/paris/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.RLP` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/utils/__init__.ast b/coq/ethereum/paris/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/paris/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/utils/__init__.v b/coq/ethereum/paris/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/paris/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/paris/utils/address.ast b/coq/ethereum/paris/utils/address.ast new file mode 100644 index 0000000000..cbd6ecbdc3 --- /dev/null +++ b/coq/ethereum/paris/utils/address.ast @@ -0,0 +1,216 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this paris version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_create2_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='salt', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='call_data', + annotation=Name(id='bytearray', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created, which is\n based on the sender address, salt and the call data as well.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n salt :\n Address generation salt.\n call_data :\n The code of the new account which is to be created.\n\n Returns\n -------\n address: `ethereum.paris.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='preimage', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Constant(value=b'\xff'), + op=Add(), + right=Name(id='address', ctx=Load())), + op=Add(), + right=Name(id='salt', ctx=Load())), + op=Add(), + right=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='call_data', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/utils/address.v b/coq/ethereum/paris/utils/address.v new file mode 100644 index 0000000000..53e8bdf381 --- /dev/null +++ b/coq/ethereum/paris/utils/address.v @@ -0,0 +1,115 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this paris version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.paris.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition compute_create2_contract_address (address : Address) (salt : Bytes32) (call_data : bytearray) : M Address := + (* + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.paris.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "preimage" [[ + (* TODO expression *) in + ]] in + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "preimage" |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/utils/hexadecimal.ast b/coq/ethereum/paris/utils/hexadecimal.ast new file mode 100644 index 0000000000..57d29d8198 --- /dev/null +++ b/coq/ethereum/paris/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to\nParis types.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/utils/hexadecimal.v b/coq/ethereum/paris/utils/hexadecimal.v new file mode 100644 index 0000000000..b2b568d375 --- /dev/null +++ b/coq/ethereum/paris/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Paris types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.paris.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/utils/message.ast b/coq/ethereum/paris/utils/message.ast new file mode 100644 index 0000000000..ff79ee01a4 --- /dev/null +++ b/coq/ethereum/paris/utils/message.ast @@ -0,0 +1,335 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this paris version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='FrozenSet'), + alias(name='Optional'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_static', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='preaccessed_addresses', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='preaccessed_storage_keys', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True), + Constant(value=False), + Call( + func=Name(id='frozenset', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='frozenset', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n is_static:\n if True then it prevents all state-changing operations from being\n executed.\n preaccessed_addresses:\n Addresses that should be marked as accessed prior to the message call\n preaccessed_storage_keys:\n Storage keys that should be marked as accessed prior to the message\n call\n\n Returns\n -------\n message: `ethereum.paris.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Assign( + targets=[ + Name(id='accessed_addresses', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='current_target', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='caller', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Name(id='preaccessed_addresses', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=Name(id='is_static', ctx=Load())), + keyword( + arg='accessed_addresses', + value=Name(id='accessed_addresses', ctx=Load())), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='preaccessed_storage_keys', ctx=Load())], + keywords=[])), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/utils/message.v b/coq/ethereum/paris/utils/message.v new file mode 100644 index 0000000000..784037d71c --- /dev/null +++ b/coq/ethereum/paris/utils/message.v @@ -0,0 +1,85 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this paris version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.paris.fork_types. +Require ethereum.paris.state. +Require ethereum.paris.vm. +Require ethereum.paris.vm.precompiled_contracts.mapping. +Require ethereum.paris.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) (is_static : bool) (preaccessed_addresses : (* TODO type *)) (preaccessed_storage_keys : (* TODO type *)) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.paris.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + do* M.assign "accessed_addresses" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "add" |) ~(| + M.get_local ~(| "current_target" |) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "add" |) ~(| + caller + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS, "keys" |) ~(| + + |) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + preaccessed_addresses + |) ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/vm/__init__.ast b/coq/ethereum/paris/vm/__init__.ast new file mode 100644 index 0000000000..9e86a7333b --- /dev/null +++ b/coq/ethereum/paris/vm/__init__.ast @@ -0,0 +1,591 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty')], + level=2), + ImportFrom( + module='precompiled_contracts', + names=[ + alias(name='RIPEMD160_ADDRESS')], + level=1), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='prev_randao', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='is_static', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_addresses', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_storage_keys', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='return_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_addresses', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_storage_keys', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + If( + test=Compare( + left=Name(id='RIPEMD160_ADDRESS', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/__init__.v b/coq/ethereum/paris/vm/__init__.v new file mode 100644 index 0000000000..1dc78dc046 --- /dev/null +++ b/coq/ethereum/paris/vm/__init__.v @@ -0,0 +1,78 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.paris.blocks. +Require ethereum.paris.fork_types. +Require ethereum.paris.state. +Require ethereum.paris.vm.precompiled_contracts. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "touched_accounts" |), "update" |) ~(| + M.get_field ~(| child_evm, "touched_accounts" |) + |) ]] in + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| child_evm, "accessed_addresses" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_storage_keys" |), "update" |) ~(| + M.get_field ~(| child_evm, "accessed_storage_keys" |) + |) ]] in + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + (* TODO statement *) + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/paris/vm/exceptions.ast b/coq/ethereum/paris/vm/exceptions.ast new file mode 100644 index 0000000000..79ecb4b47d --- /dev/null +++ b/coq/ethereum/paris/vm/exceptions.ast @@ -0,0 +1,175 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='Revert', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised by the `REVERT` opcode.\n\n Unlike other EVM exceptions this does not result in the consumption of all\n gas.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='WriteInStaticContext', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt is made to modify the state while operating inside\n of a STATICCALL context.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfBoundsRead', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt was made to read data beyond the\n boundaries of the buffer.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidParameter', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when invalid parameters are passed.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidContractPrefix', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract code starts with 0xEF.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/exceptions.v b/coq/ethereum/paris/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/paris/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/paris/vm/gas.ast b/coq/ethereum/paris/vm/gas.ast new file mode 100644 index 0000000000..33b4cae82f --- /dev/null +++ b/coq/ethereum/paris/vm/gas.ast @@ -0,0 +1,813 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=4800)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RETURN_DATA_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_FAST_STEP', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLAKE2_PER_ROUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COLD_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2100)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_WARM_ACCESS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=100)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_left', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='memory_cost', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='extra_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='call_stipend', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Expr( + value=Constant(value='\n Calculates the MessageCallGas (cost and stipend) for\n executing call Opcodes.\n\n Parameters\n ----------\n value:\n The amount of `ETH` that needs to be transferred.\n gas :\n The amount of gas provided to the message-call.\n gas_left :\n The amount of gas left in the current frame.\n memory_cost :\n The amount needed to extend the memory in the current frame.\n extra_gas :\n The amount of gas needed for transferring value + creating a new\n account inside a message call.\n call_stipend :\n The amount of stipend provided to a message call to execute code while\n transferring value(ETH).\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='call_stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='call_stipend', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='extra_gas', ctx=Load()), + op=Add(), + right=Name(id='memory_cost', ctx=Load()))]), + body=[ + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='gas', ctx=Load()), + Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='gas_left', ctx=Load()), + op=Sub(), + right=Name(id='memory_cost', ctx=Load())), + op=Sub(), + right=Name(id='extra_gas', ctx=Load()))], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load())), + FunctionDef( + name='max_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the maximum gas that is allowed for making a message call\n\n Parameters\n ----------\n gas :\n The amount of gas provided to the message-call.\n\n Returns\n -------\n max_allowed_message_call_gas: `ethereum.base_types.Uint`\n The maximum gas allowed for making the message-call.\n ')), + Return( + value=BinOp( + left=Name(id='gas', ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='gas', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]))))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/gas.v b/coq/ethereum/paris/vm/gas.v new file mode 100644 index 0000000000..3085866d46 --- /dev/null +++ b/coq/ethereum/paris/vm/gas.v @@ -0,0 +1,171 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (value : U256) (gas : Uint) (gas_left : Uint) (memory_cost : Uint) (extra_gas : Uint) (call_stipend : Uint) : M MessageCallGas := + (* + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "gas" [[ + M.get_local ~(| "min" |) ~(| + gas, + M.get_local ~(| "max_message_call_gas" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition max_message_call_gas (gas : Uint) : M Uint := + (* + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/vm/instructions/__init__.ast b/coq/ethereum/paris/vm/instructions/__init__.ast new file mode 100644 index 0000000000..90d4d078a3 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/__init__.ast @@ -0,0 +1,1792 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='SHL', ctx=Store())], + value=Constant(value=27)), + Assign( + targets=[ + Name(id='SHR', ctx=Store())], + value=Constant(value=28)), + Assign( + targets=[ + Name(id='SAR', ctx=Store())], + value=Constant(value=29)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='RETURNDATASIZE', ctx=Store())], + value=Constant(value=61)), + Assign( + targets=[ + Name(id='RETURNDATACOPY', ctx=Store())], + value=Constant(value=62)), + Assign( + targets=[ + Name(id='EXTCODEHASH', ctx=Store())], + value=Constant(value=63)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='PREVRANDAO', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='CHAINID', ctx=Store())], + value=Constant(value=70)), + Assign( + targets=[ + Name(id='SELFBALANCE', ctx=Store())], + value=Constant(value=71)), + Assign( + targets=[ + Name(id='BASEFEE', ctx=Store())], + value=Constant(value=72)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='CREATE2', ctx=Store())], + value=Constant(value=245)), + Assign( + targets=[ + Name(id='STATICCALL', ctx=Store())], + value=Constant(value=250)), + Assign( + targets=[ + Name(id='REVERT', ctx=Store())], + value=Constant(value=253)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SAR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PREVRANDAO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CHAINID', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODEHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFBALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BASEFEE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STATICCALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='REVERT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE2', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shl', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shr', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_sar', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='prev_randao', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodehash', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='self_balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='base_fee', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='staticcall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='revert', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create2', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/instructions/__init__.v b/coq/ethereum/paris/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/paris/vm/instructions/arithmetic.ast b/coq/ethereum/paris/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/instructions/arithmetic.v b/coq/ethereum/paris/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..0e608dadc9 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/paris/vm/instructions/bitwise.ast b/coq/ethereum/paris/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..b72397f0ec --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/bitwise.ast @@ -0,0 +1,751 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shl', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift left (SHL) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='value', ctx=Load()), + op=LShift(), + right=Name(id='shift', ctx=Load())), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]))], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shr', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift right (SHR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_sar', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Arithmetic shift right (SAR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='signed_value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=256)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + BinOp( + left=Name(id='signed_value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load()))], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='signed_value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load()))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/instructions/bitwise.v b/coq/ethereum/paris/vm/instructions/bitwise.v new file mode 100644 index 0000000000..cf138e1a25 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/bitwise.v @@ -0,0 +1,309 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shl (evm : Evm) : M unit := + (* + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shr (evm : Evm) : M unit := + (* + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_sar (evm : Evm) : M unit := + (* + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + M.get_local ~(| "int" |) ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "signed_value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/paris/vm/instructions/block.ast b/coq/ethereum/paris/vm/instructions/block.ast new file mode 100644 index 0000000000..70810f2e06 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/block.ast @@ -0,0 +1,495 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.paris.vm.exceptions.StackUnderflowError`\n If `len(stack)` is less than `1`.\n :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `20`.\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='prev_randao', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the `prev_randao` value onto the stack.\n\n The `prev_randao` value is the random output of the beacon chain's\n randomness oracle for the previous block.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='prev_randao', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='chain_id', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the chain id onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/instructions/block.v b/coq/ethereum/paris/vm/instructions/block.v new file mode 100644 index 0000000000..0b1cc9b5f7 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/block.v @@ -0,0 +1,283 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.paris.vm.exceptions.StackUnderflowError` + If `len(stack)` is less than `1`. + :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `20`. + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition prev_randao (evm : Evm) : M unit := + (* + Push the `prev_randao` value onto the stack. + + The `prev_randao` value is the random output of the beacon chain's + randomness oracle for the previous block. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "prev_randao" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition chain_id (evm : Evm) : M unit := + (* + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.paris.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.paris.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/paris/vm/instructions/comparison.ast b/coq/ethereum/paris/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/instructions/comparison.v b/coq/ethereum/paris/vm/instructions/comparison.v new file mode 100644 index 0000000000..31e39f4445 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/paris/vm/instructions/control_flow.ast b/coq/ethereum/paris/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/instructions/control_flow.v b/coq/ethereum/paris/vm/instructions/control_flow.v new file mode 100644 index 0000000000..c104e50c98 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.exceptions. +Require ethereum.paris.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/paris/vm/instructions/environment.ast b/coq/ethereum/paris/vm/instructions/environment.ast new file mode 100644 index 0000000000..60bbfdaff1 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/environment.ast @@ -0,0 +1,1828 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfBoundsRead')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_COLD_ACCOUNT_ACCESS'), + alias(name='GAS_COPY'), + alias(name='GAS_FAST_STEP'), + alias(name='GAS_RETURN_DATA_COPY'), + alias(name='GAS_VERY_LOW'), + alias(name='GAS_WARM_ACCESS'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_WARM_ACCESS', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the size of the return data buffer onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copies data from the return data buffer code to memory\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='return_data_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_RETURN_DATA_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='return_data_start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfBoundsRead', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load()), + slice=Slice( + lower=Name(id='return_data_start_position', ctx=Load()), + upper=BinOp( + left=Name(id='return_data_start_position', ctx=Load()), + op=Add(), + right=Name(id='size', ctx=Load()))), + ctx=Load())), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodehash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns the keccak256 hash of a contract’s bytecode\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='EMPTY_ACCOUNT', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codehash', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='self_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the current address to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_FAST_STEP', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='base_fee', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the base fee of the current block on to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/instructions/environment.v b/coq/ethereum/paris/vm/instructions/environment.v new file mode 100644 index 0000000000..62f70fc204 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/environment.v @@ -0,0 +1,728 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.paris.fork_types. +Require ethereum.paris.state. +Require ethereum.paris.utils.address. +Require ethereum.paris.vm.memory. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.exceptions. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatasize (evm : Evm) : M unit := + (* + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatacopy (evm : Evm) : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "return_data_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + (* TODO expression *) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodehash (evm : Evm) : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "account" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codehash" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition self_balance (evm : Evm) : M unit := + (* + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_FAST_STEP + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition base_fee (evm : Evm) : M unit := + (* + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "base_fee_per_gas" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/paris/vm/instructions/keccak.ast b/coq/ethereum/paris/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/instructions/keccak.v b/coq/ethereum/paris/vm/instructions/keccak.v new file mode 100644 index 0000000000..a56cf7ecab --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.memory. +Require ethereum.paris.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/paris/vm/instructions/log.ast b/coq/ethereum/paris/vm/instructions/log.ast new file mode 100644 index 0000000000..0ded0e04ba --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/log.ast @@ -0,0 +1,323 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/instructions/log.v b/coq/ethereum/paris/vm/instructions/log.v new file mode 100644 index 0000000000..2c4b57f004 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/log.v @@ -0,0 +1,79 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.paris.blocks. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.exceptions. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.memory. +Require ethereum.paris.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO statement *) + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/paris/vm/instructions/memory.ast b/coq/ethereum/paris/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/instructions/memory.v b/coq/ethereum/paris/vm/instructions/memory.v new file mode 100644 index 0000000000..c134d6071b --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.memory. +Require ethereum.paris.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/paris/vm/instructions/stack.ast b/coq/ethereum/paris/vm/instructions/stack.ast new file mode 100644 index 0000000000..95cfc0b6cf --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/stack.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/instructions/stack.v b/coq/ethereum/paris/vm/instructions/stack.v new file mode 100644 index 0000000000..7c7a73c495 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/stack.v @@ -0,0 +1,153 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.exceptions. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/paris/vm/instructions/storage.ast b/coq/ethereum/paris/vm/instructions/storage.ast new file mode 100644 index 0000000000..68640a90a8 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/storage.ast @@ -0,0 +1,551 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='get_storage_original'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_STIPEND'), + alias(name='GAS_COLD_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='GAS_WARM_ACCESS'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_SLOAD', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='get_storage_original', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + If( + test=Compare( + left=Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_COLD_SLOAD', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='current_value', ctx=Load())]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())])]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_COLD_SLOAD', ctx=Load())))])], + orelse=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))]), + If( + test=Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='GAS_STORAGE_SET', ctx=Load()), + op=Sub(), + right=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + keywords=[]))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_COLD_SLOAD', ctx=Load())), + op=Sub(), + right=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + keywords=[]))])], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/instructions/storage.v b/coq/ethereum/paris/vm/instructions/storage.v new file mode 100644 index 0000000000..cdaea2ef59 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/storage.v @@ -0,0 +1,121 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.paris.state. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.exceptions. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "original_value" [[ + state.get_storage_original ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "gas_cost" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/paris/vm/instructions/system.ast b/coq/ethereum/paris/vm/instructions/system.ast new file mode 100644 index 0000000000..0fcb1135df --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/system.ast @@ -0,0 +1,2897 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='is_account_alive'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='compute_create2_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='Revert'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_VALUE'), + alias(name='GAS_COLD_ACCOUNT_ACCESS'), + alias(name='GAS_CREATE'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='GAS_NEW_ACCOUNT'), + alias(name='GAS_SELF_DESTRUCT'), + alias(name='GAS_SELF_DESTRUCT_NEW_ACCOUNT'), + alias(name='GAS_WARM_ACCESS'), + alias(name='GAS_ZERO'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas'), + alias(name='max_message_call_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='generic_create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='endowment', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='contract_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='memory_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Core logic used by the `CREATE*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='contract_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='create_message_gas', ctx=Load())), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='is_static', + value=Constant(value=False)), + keyword( + arg='accessed_addresses', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create2', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Creates a new account with associated code.\n\n It's similar to CREATE opcode except that the address of new account\n depends on the init_code instead of the nonce of sender.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ")), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='salt', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='call_data_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='call_data_words', ctx=Load()))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_create2_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='salt', ctx=Load()), + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_staticcall', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=IfExp( + test=Name(id='is_staticcall', ctx=Load()), + body=Constant(value=True), + orelse=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()))), + keyword( + arg='accessed_addresses', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='to', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=BoolOp( + op=Or(), + values=[ + Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[]), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='access_gas_cost', ctx=Load()), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='code_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=Name(id='access_gas_cost', ctx=Load()), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SELF_DESTRUCT', ctx=Load())), + If( + test=Compare( + left=Name(id='beneficiary', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[])), + Compare( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='code_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='access_gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='staticcall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='to', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='access_gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='revert', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop execution and revert state changes, without consuming all provided gas\n and also has the ability to return a reason\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Name(id='output', ctx=Load())], + keywords=[])), + Raise( + exc=Name(id='Revert', ctx=Load())), + Pass()], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/instructions/system.v b/coq/ethereum/paris/vm/instructions/system.v new file mode 100644 index 0000000000..1740ce8ae4 --- /dev/null +++ b/coq/ethereum/paris/vm/instructions/system.v @@ -0,0 +1,779 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.paris.fork_types. +Require ethereum.paris.state. +Require ethereum.paris.utils.address. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.exceptions. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.memory. +Require ethereum.paris.vm.stack. + +Definition generic_create (evm : Evm) (endowment : U256) (contract_address : Address) (memory_start_position : U256) (memory_size : U256) : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "add" |) ~(| + contract_address + |) ]] in + do* M.assign "create_message_gas" [[ + gas.max_message_call_gas ~(| + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) in + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_local ~(| "create_message_gas" |) + ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_start_position, + memory_size + |) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_create_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition create2 (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "salt" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "call_data_words" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_create2_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "salt" |), + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (is_staticcall : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_SELF_DESTRUCT in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + M.get_local ~(| "access_gas_cost" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition staticcall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + M.get_local ~(| "access_gas_cost" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "to" |), + M.get_local ~(| "to" |), + True, + True, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition revert (evm : Evm) : M unit := + (* + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "output" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/vm/interpreter.ast b/coq/ethereum/paris/vm/interpreter.ast new file mode 100644 index 0000000000..235b2b9ec0 --- /dev/null +++ b/coq/ethereum/paris/vm/interpreter.ast @@ -0,0 +1,1188 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Iterable'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='increment_nonce'), + alias(name='mark_account_created'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidContractPrefix'), + alias(name='InvalidOpcode'), + alias(name='OutOfGasError'), + alias(name='Revert'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_CODE_SIZE', ctx=Store())], + value=Constant(value=24576)), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `touched_accounts`: Accounts that have been touched.\n 6. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple(elts=[], ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='touched_accounts', + value=Name(id='touched_accounts', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.paris.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='mark_account_created', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='contract_code', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=239)]), + body=[ + Raise( + exc=Name(id='InvalidContractPrefix', ctx=Load()))], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_CODE_SIZE', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.paris.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='touched_accounts', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='return_data', + value=Constant(value=b'')), + keyword( + arg='error', + value=Constant(value=None)), + keyword( + arg='accessed_addresses', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='accessed_addresses', + ctx=Load())), + keyword( + arg='accessed_storage_keys', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))]), + ExceptHandler( + type=Name(id='Revert', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/interpreter.v b/coq/ethereum/paris/vm/interpreter.v new file mode 100644 index 0000000000..fa53be1727 --- /dev/null +++ b/coq/ethereum/paris/vm/interpreter.v @@ -0,0 +1,173 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.paris.blocks. +Require ethereum.paris.fork_types. +Require ethereum.paris.state. +Require ethereum.paris.vm. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.precompiled_contracts.mapping. +Require ethereum.paris.vm.__init__. +Require ethereum.paris.vm.exceptions. +Require ethereum.paris.vm.instructions. +Require ethereum.paris.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.paris.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.mark_account_created ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.paris.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/vm/memory.ast b/coq/ethereum/paris/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/paris/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/memory.v b/coq/ethereum/paris/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/paris/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/vm/precompiled_contracts/__init__.ast b/coq/ethereum/paris/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..bb9991907f --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS'), + Constant(value='MODEXP_ADDRESS'), + Constant(value='ALT_BN128_ADD_ADDRESS'), + Constant(value='ALT_BN128_MUL_ADDRESS'), + Constant(value='ALT_BN128_PAIRING_CHECK_ADDRESS'), + Constant(value='BLAKE2F_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[])), + Assign( + targets=[ + Name(id='MODEXP_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x05')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x06')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x07')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x08')], + keywords=[])), + Assign( + targets=[ + Name(id='BLAKE2F_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x09')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/precompiled_contracts/__init__.v b/coq/ethereum/paris/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..46a71b60f2 --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.paris.utils.hexadecimal. diff --git a/coq/ethereum/paris/vm/precompiled_contracts/alt_bn128.ast b/coq/ethereum/paris/vm/precompiled_contracts/alt_bn128.ast new file mode 100644 index 0000000000..f6f077419c --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/alt_bn128.ast @@ -0,0 +1,913 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ALT_BN128 CONTRACTS\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ALT_BN128 precompiled contracts.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.alt_bn128', + names=[ + alias(name='ALT_BN128_CURVE_ORDER'), + alias(name='ALT_BN128_PRIME'), + alias(name='BNF'), + alias(name='BNF2'), + alias(name='BNF12'), + alias(name='BNP'), + alias(name='BNP2'), + alias(name='pairing')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=2), + FunctionDef( + name='alt_bn128_add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 addition precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=150)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load()), + Name(id='x1_value', ctx=Load()), + Name(id='y1_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='p1', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x1_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y1_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=BinOp( + left=Name(id='p0', ctx=Load()), + op=Add(), + right=Name(id='p1', ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 multiplication precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6000)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='n', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='p0', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='n', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_pairing_check', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 pairing check precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=34000), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))), + op=Add(), + right=Constant(value=45000))], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=192)), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='values', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=Name(id='j', ctx=Load()))), + upper=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=BinOp( + left=Name(id='j', ctx=Load()), + op=Add(), + right=Constant(value=1))))), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='values', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=Call( + func=Name(id='BNP2', ctx=Load()), + args=[ + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=3), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=2), + ctx=Load())], + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=5), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=4), + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='OutOfGasError', ctx=Load()), + args=[], + keywords=[]))])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='p', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='q', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='p', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + Compare( + left=Name(id='q', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='result', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='pairing', ctx=Load()), + args=[ + Name(id='q', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[])))], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='result', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/paris/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000000..90ed0d3513 --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,226 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.alt_bn128. +Require ethereum.paris.vm. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.memory. +Require ethereum.paris.vm.exceptions. + +Definition alt_bn128_add (evm : Evm) : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 150 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "x1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x1_bytes" |) + |) + |) in + ]] in + do* M.assign "y1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y1_bytes" |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + (* TODO expression *) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_mul (evm : Evm) : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 6000 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "n" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + M.get_field ~(| M.get_local ~(| "p0" |), "mul_by" |) ~(| + M.get_local ~(| "n" |) + |) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_pairing_check (evm : Evm) : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + (* TODO expression *) + |) + |) ]] in + (* TODO statement *) + do* M.assign "result" [[ + M.get_field ~(| ethereum.crypto.alt_bn128.BNF12, "from_int" |) ~(| + 1 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/vm/precompiled_contracts/blake2f.ast b/coq/ethereum/paris/vm/precompiled_contracts/blake2f.ast new file mode 100644 index 0000000000..03747962f0 --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/blake2f.ast @@ -0,0 +1,137 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `Blake2` precompiled contract.\n')), + ImportFrom( + module='ethereum.crypto.blake2', + names=[ + alias(name='Blake2b')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BLAKE2_PER_ROUND'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidParameter')], + level=2), + FunctionDef( + name='blake2f', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the Blake2 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Constant(value=213)]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='blake2b', ctx=Store())], + value=Call( + func=Name(id='Blake2b', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='rounds', ctx=Store()), + Name(id='h', ctx=Store()), + Name(id='m', ctx=Store()), + Name(id='t_0', ctx=Store()), + Name(id='t_1', ctx=Store()), + Name(id='f', ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='get_blake2_parameters', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_BLAKE2_PER_ROUND', ctx=Load()), + op=Mult(), + right=Name(id='rounds', ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=Name(id='f', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + List( + elts=[ + Constant(value=0), + Constant(value=1)], + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='compress', + ctx=Load()), + args=[ + Name(id='rounds', ctx=Load()), + Name(id='h', ctx=Load()), + Name(id='m', ctx=Load()), + Name(id='t_0', ctx=Load()), + Name(id='t_1', ctx=Load()), + Name(id='f', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/precompiled_contracts/blake2f.v b/coq/ethereum/paris/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000000..5042c50aca --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,46 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +*) + +Require ethereum.crypto.blake2. +Require ethereum.paris.vm. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.exceptions. + +Definition blake2f (evm : Evm) : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + (* TODO statement *) + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| + + |) in + ]] in + (* TODO assignment *) + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/paris/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/paris/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/paris/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..04c9ebc232 --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.paris.vm. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/paris/vm/precompiled_contracts/identity.ast b/coq/ethereum/paris/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/precompiled_contracts/identity.v b/coq/ethereum/paris/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..d90d95a7aa --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.paris.vm. +Require ethereum.paris.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/paris/vm/precompiled_contracts/mapping.ast b/coq/ethereum/paris/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..cec40e5736 --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ALT_BN128_ADD_ADDRESS'), + alias(name='ALT_BN128_MUL_ADDRESS'), + alias(name='ALT_BN128_PAIRING_CHECK_ADDRESS'), + alias(name='BLAKE2F_ADDRESS'), + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='MODEXP_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='alt_bn128', + names=[ + alias(name='alt_bn128_add'), + alias(name='alt_bn128_mul'), + alias(name='alt_bn128_pairing_check')], + level=1), + ImportFrom( + module='blake2f', + names=[ + alias(name='blake2f')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='modexp', + names=[ + alias(name='modexp')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load()), + Name(id='MODEXP_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Load()), + Name(id='BLAKE2F_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load()), + Name(id='modexp', ctx=Load()), + Name(id='alt_bn128_add', ctx=Load()), + Name(id='alt_bn128_mul', ctx=Load()), + Name(id='alt_bn128_pairing_check', ctx=Load()), + Name(id='blake2f', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/precompiled_contracts/mapping.v b/coq/ethereum/paris/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..07b1615a06 --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/mapping.v @@ -0,0 +1,25 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.paris.fork_types. +Require ethereum.paris.vm.precompiled_contracts.__init__. +Require ethereum.paris.vm.precompiled_contracts.alt_bn128. +Require ethereum.paris.vm.precompiled_contracts.blake2f. +Require ethereum.paris.vm.precompiled_contracts.ecrecover. +Require ethereum.paris.vm.precompiled_contracts.identity. +Require ethereum.paris.vm.precompiled_contracts.modexp. +Require ethereum.paris.vm.precompiled_contracts.ripemd160. +Require ethereum.paris.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/paris/vm/precompiled_contracts/modexp.ast b/coq/ethereum/paris/vm/precompiled_contracts/modexp.ast new file mode 100644 index 0000000000..42ecfa223f --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/modexp.ast @@ -0,0 +1,638 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `MODEXP` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + Assign( + targets=[ + Name(id='GQUADDIVISOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + FunctionDef( + name='modexp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and.\n `modulus`. The return value is the same length as the modulus.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='base_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_start', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Add(), + right=Name(id='base_length', ctx=Load()))), + Assign( + targets=[ + Name(id='exp_head', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Call( + func=Name(id='min', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='gas_cost', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load()), + Name(id='exp_length', ctx=Load()), + Name(id='exp_head', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='base_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='modulus_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Name(id='base_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_start', ctx=Store())], + value=BinOp( + left=Name(id='exp_start', ctx=Load()), + op=Add(), + right=Name(id='exp_length', ctx=Load()))), + Assign( + targets=[ + Name(id='modulus', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='modulus_start', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='modulus', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'\x00')], + keywords=[]), + op=Mult(), + right=Name(id='modulus_length', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exp', ctx=Load()), + Name(id='modulus', ctx=Load())], + keywords=[]), + attr='to_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[]), + Constant(value='big')], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='complexity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Estimate the complexity of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n Returns\n -------\n\n complexity : `Uint`\n Complexity of performing the operation.\n ')), + Assign( + targets=[ + Name(id='max_length', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load())], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Return( + value=BinOp( + left=Name(id='words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='iterations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the number of iterations required to perform a modular\n exponentiation.\n\n Parameters\n ----------\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n iterations : `Uint`\n Number of iterations.\n ')), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + Compare( + left=Name(id='exponent_head', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='bit_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='bit_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='bit_length', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Name(id='bit_length', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='length_part', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])))), + Assign( + targets=[ + Name(id='bits_part', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='bits_part', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='bits_part', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=BinOp( + left=Name(id='length_part', ctx=Load()), + op=Add(), + right=Name(id='bits_part', ctx=Load())))])]), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='count', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the gas cost of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n gas_cost : `Uint`\n Gas required for performing the operation.\n ')), + Assign( + targets=[ + Name(id='multiplication_complexity', ctx=Store())], + value=Call( + func=Name(id='complexity', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='iteration_count', ctx=Store())], + value=Call( + func=Name(id='iterations', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load()), + Name(id='exponent_head', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cost', ctx=Store())], + value=BinOp( + left=Name(id='multiplication_complexity', ctx=Load()), + op=Mult(), + right=Name(id='iteration_count', ctx=Load()))), + AugAssign( + target=Name(id='cost', ctx=Store()), + op=FloorDiv(), + value=Name(id='GQUADDIVISOR', ctx=Load())), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[]), + Name(id='cost', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/precompiled_contracts/modexp.v b/coq/ethereum/paris/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000000..3ec8f5b2af --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/modexp.v @@ -0,0 +1,236 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.paris.vm. +Require ethereum.paris.vm.gas. +Require ethereum.paris.vm.memory. + +Definition modexp (evm : Evm) : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "base_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "modulus_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "exp_head" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "min" |) ~(| + ethereum_types.numeric.U256 ~(| + 32 + |), + M.get_local ~(| "exp_length" |) + |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) ~(| + M.get_local ~(| "base_length" |), + M.get_local ~(| "modulus_length" |), + M.get_local ~(| "exp_length" |), + M.get_local ~(| "exp_head" |) + |) + |) ]] in + (* TODO statement *) + do* M.assign "base" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + M.get_local ~(| "base_length" |) + |) + |) in + ]] in + do* M.assign "exp" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "exp_length" |) + |) + |) in + ]] in + do* M.assign "modulus_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "modulus" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "modulus_start" |), + M.get_local ~(| "modulus_length" |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := + (* + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + *) + do* M.assign "max_length" [[ + M.get_local ~(| "max" |) ~(| + ethereum_types.numeric.Uint ~(| + base_length + |), + ethereum_types.numeric.Uint ~(| + modulus_length + |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition gas_cost (base_length : U256) (modulus_length : U256) (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + *) + do* M.assign "multiplication_complexity" [[ + M.get_local ~(| "complexity" |) ~(| + base_length, + modulus_length + |) in + ]] in + do* M.assign "iteration_count" [[ + M.get_local ~(| "iterations" |) ~(| + exponent_length, + exponent_head + |) in + ]] in + do* M.assign "cost" [[ + (* TODO expression *) in + ]] in + do* M.aug_assign [[ M.get_local ~(| "cost" |) ]] [[ + M.get_local ~(| "GQUADDIVISOR" |) + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/paris/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/paris/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/paris/vm/precompiled_contracts/sha256.ast b/coq/ethereum/paris/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/precompiled_contracts/sha256.v b/coq/ethereum/paris/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/paris/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/paris/vm/runtime.ast b/coq/ethereum/paris/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/paris/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/runtime.v b/coq/ethereum/paris/vm/runtime.v new file mode 100644 index 0000000000..4e79d9dd32 --- /dev/null +++ b/coq/ethereum/paris/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.paris.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/paris/vm/stack.ast b/coq/ethereum/paris/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/paris/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/paris/vm/stack.v b/coq/ethereum/paris/vm/stack.v new file mode 100644 index 0000000000..5f42af2fee --- /dev/null +++ b/coq/ethereum/paris/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.paris.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/rlp.ast b/coq/ethereum/rlp.ast new file mode 100644 index 0000000000..e361687123 --- /dev/null +++ b/coq/ethereum/rlp.ast @@ -0,0 +1,2259 @@ +Module( + body=[ + Expr( + value=Constant(value='\n.. _rlp:\n\nRecursive Length Prefix (RLP) Encoding\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nDefines the serialization and deserialization format used throughout Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='astuple'), + alias(name='fields'), + alias(name='is_dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Any'), + alias(name='ClassVar'), + alias(name='Dict'), + alias(name='Protocol'), + alias(name='Sequence'), + alias(name='Tuple'), + alias(name='Type'), + alias(name='TypeAlias'), + alias(name='TypeVar'), + alias(name='Union'), + alias(name='cast'), + alias(name='get_args'), + alias(name='get_origin'), + alias(name='get_type_hints'), + alias(name='overload')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='FixedBytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='FixedUnsigned'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='RLPDecodingError'), + alias(name='RLPEncodingError')], + level=0), + ClassDef( + name='RLP', + bases=[ + Name(id='Protocol', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n [`Protocol`] that describes the requirements to be RLP-encodable.\n\n [`Protocol`]: https://docs.python.org/3/library/typing.html#typing.Protocol\n ')), + AnnAssign( + target=Name(id='__dataclass_fields__', ctx=Store()), + annotation=Subscript( + value=Name(id='ClassVar', ctx=Load()), + slice=Name(id='Dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[]), + AnnAssign( + target=Name(id='Simple', ctx=Store()), + annotation=Name(id='TypeAlias', ctx=Load()), + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Constant(value='Simple'), + ctx=Load()), + Name(id='bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='Extended', ctx=Store()), + annotation=Name(id='TypeAlias', ctx=Load()), + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Constant(value='Extended'), + ctx=Load()), + Name(id='bytearray', ctx=Load()), + Name(id='bytes', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='FixedUnsigned', ctx=Load()), + Name(id='str', ctx=Load()), + Name(id='bool', ctx=Load()), + Name(id='RLP', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + FunctionDef( + name='encode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_data', + annotation=Name(id='Extended', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes `raw_data` into a sequence of bytes using RLP.\n\n Parameters\n ----------\n raw_data :\n A `Bytes`, `Uint`, `Uint256` or sequence of `RLP` encodable\n objects.\n\n Returns\n -------\n encoded : `ethereum.base_types.Bytes`\n The RLP encoded bytes representing `raw_data`.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='raw_data', ctx=Load()), + Name(id='Sequence', ctx=Load())], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='raw_data', ctx=Load()), + Tuple( + elts=[ + Name(id='bytearray', ctx=Load()), + Name(id='bytes', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='encode_bytes', ctx=Load()), + args=[ + Name(id='raw_data', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='raw_data', ctx=Load()), + Name(id='str', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='encode_bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw_data', ctx=Load()), + attr='encode', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Return( + value=Call( + func=Name(id='encode_sequence', ctx=Load()), + args=[ + Name(id='raw_data', ctx=Load())], + keywords=[]))])])], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='raw_data', ctx=Load()), + Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='FixedUnsigned', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='encode', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw_data', ctx=Load()), + attr='to_be_bytes', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='raw_data', ctx=Load()), + Name(id='bool', ctx=Load())], + keywords=[]), + body=[ + If( + test=Name(id='raw_data', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='encode_bytes', ctx=Load()), + args=[ + Constant(value=b'\x01')], + keywords=[]))], + orelse=[ + Return( + value=Call( + func=Name(id='encode_bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[]))])], + orelse=[ + If( + test=Call( + func=Name(id='is_dataclass', ctx=Load()), + args=[ + Name(id='raw_data', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='encode', ctx=Load()), + args=[ + Call( + func=Name(id='astuple', ctx=Load()), + args=[ + Name(id='raw_data', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Raise( + exc=Call( + func=Name(id='RLPEncodingError', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Constant(value='RLP Encoding of type {} is not supported'), + attr='format', + ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='raw_data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))])])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='encode_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_bytes', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes `raw_bytes`, a sequence of bytes, using RLP.\n\n Parameters\n ----------\n raw_bytes :\n Bytes to encode with RLP.\n\n Returns\n -------\n encoded : `ethereum.base_types.Bytes`\n The RLP encoded bytes representing `raw_bytes`.\n ')), + Assign( + targets=[ + Name(id='len_raw_data', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='raw_bytes', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='len_raw_data', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + Compare( + left=Subscript( + value=Name(id='raw_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=128)])]), + body=[ + Return( + value=Name(id='raw_bytes', ctx=Load()))], + orelse=[ + If( + test=Compare( + left=Name(id='len_raw_data', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=56)]), + body=[ + Return( + value=BinOp( + left=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Constant(value=128), + op=Add(), + right=Name(id='len_raw_data', ctx=Load()))], + ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='raw_bytes', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='len_raw_data_as_be', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='len_raw_data', ctx=Load())], + keywords=[]), + attr='to_be_bytes', + ctx=Load()), + args=[], + keywords=[])), + Return( + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Constant(value=183), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='len_raw_data_as_be', ctx=Load())], + keywords=[]))], + ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='len_raw_data_as_be', ctx=Load())), + op=Add(), + right=Name(id='raw_bytes', ctx=Load())))])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='encode_sequence', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_sequence', + annotation=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Extended', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a list of RLP encodable objects (`raw_sequence`) using RLP.\n\n Parameters\n ----------\n raw_sequence :\n Sequence of RLP encodable objects.\n\n Returns\n -------\n encoded : `ethereum.base_types.Bytes`\n The RLP encoded bytes representing `raw_sequence`.\n ')), + Assign( + targets=[ + Name(id='joined_encodings', ctx=Store())], + value=Call( + func=Name(id='get_joined_encodings', ctx=Load()), + args=[ + Name(id='raw_sequence', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='len_joined_encodings', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='joined_encodings', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='len_joined_encodings', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=56)]), + body=[ + Return( + value=BinOp( + left=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Constant(value=192), + op=Add(), + right=Name(id='len_joined_encodings', ctx=Load()))], + ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='joined_encodings', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='len_joined_encodings_as_be', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='len_joined_encodings', ctx=Load())], + keywords=[]), + attr='to_be_bytes', + ctx=Load()), + args=[], + keywords=[])), + Return( + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Constant(value=247), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='len_joined_encodings_as_be', ctx=Load())], + keywords=[]))], + ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='len_joined_encodings_as_be', ctx=Load())), + op=Add(), + right=Name(id='joined_encodings', ctx=Load())))])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='get_joined_encodings', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_sequence', + annotation=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Extended', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain concatenation of rlp encoding for each item in the sequence\n raw_sequence.\n\n Parameters\n ----------\n raw_sequence :\n Sequence to encode with RLP.\n\n Returns\n -------\n joined_encodings : `ethereum.base_types.Bytes`\n The concatenated RLP encoded bytes for each item in sequence\n raw_sequence.\n ')), + Return( + value=Call( + func=Attribute( + value=Constant(value=b''), + attr='join', + ctx=Load()), + args=[ + GeneratorExp( + elt=Call( + func=Name(id='encode', ctx=Load()), + args=[ + Name(id='item', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='item', ctx=Store()), + iter=Name(id='raw_sequence', ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='decode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='encoded_data', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decodes an integer, byte sequence, or list of RLP encodable objects\n from the byte sequence `encoded_data`, using RLP.\n\n Parameters\n ----------\n encoded_data :\n A sequence of bytes, in RLP form.\n\n Returns\n -------\n decoded_data : `RLP`\n Object decoded from `encoded_data`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded_data', ctx=Load())], + keywords=[]), + ops=[ + LtE()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Call( + func=Name(id='RLPDecodingError', ctx=Load()), + args=[ + Constant(value='Cannot decode empty bytestring')], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Subscript( + value=Name(id='encoded_data', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Constant(value=191)]), + body=[ + Return( + value=Call( + func=Name(id='decode_to_bytes', ctx=Load()), + args=[ + Name(id='encoded_data', ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Call( + func=Name(id='decode_to_sequence', ctx=Load()), + args=[ + Name(id='encoded_data', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Simple', ctx=Load())), + Assign( + targets=[ + Name(id='U', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='U')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Extended', ctx=Load()))])), + FunctionDef( + name='decode_to', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='U', ctx=Load()), + ctx=Load())), + arg( + arg='encoded_data', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decode the bytes in `encoded_data` to an object of type `cls`. `cls` can be\n a `Bytes` subclass, a dataclass, `Uint`, `U256` or `Tuple[cls]`.\n\n Parameters\n ----------\n cls: `Type[U]`\n The type to decode to.\n encoded_data :\n A sequence of bytes, in RLP form.\n\n Returns\n -------\n decoded_data : `U`\n Object decoded from `encoded_data`.\n ')), + Assign( + targets=[ + Name(id='decoded', ctx=Store())], + value=Call( + func=Name(id='decode', ctx=Load()), + args=[ + Name(id='encoded_data', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='_deserialize_to', ctx=Load()), + args=[ + Name(id='cls', ctx=Load()), + Name(id='decoded', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='_deserialize_to', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='class_', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='U', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='Simple', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Pass()], + decorator_list=[ + Name(id='overload', ctx=Load())], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='_deserialize_to', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='class_', + annotation=Name(id='object', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Simple', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Pass()], + decorator_list=[ + Name(id='overload', ctx=Load())], + returns=Name(id='Extended', ctx=Load())), + FunctionDef( + name='_deserialize_to', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='class_', + annotation=Name(id='object', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Simple', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='class_', ctx=Load()), + Name(id='type', ctx=Load())], + keywords=[])), + body=[ + Return( + value=Call( + func=Name(id='_deserialize_to_annotation', ctx=Load()), + args=[ + Name(id='class_', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='is_dataclass', ctx=Load()), + args=[ + Name(id='class_', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='_deserialize_to_dataclass', ctx=Load()), + args=[ + Name(id='class_', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='issubclass', ctx=Load()), + args=[ + Name(id='class_', ctx=Load()), + Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='FixedUnsigned', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='_deserialize_to_uint', ctx=Load()), + args=[ + Name(id='class_', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='issubclass', ctx=Load()), + args=[ + Name(id='class_', ctx=Load()), + Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='FixedBytes', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='_deserialize_to_bytes', ctx=Load()), + args=[ + Name(id='class_', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='class_', ctx=Load()), + ops=[ + Is()], + comparators=[ + Name(id='bool', ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='_deserialize_to_bool', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[ + Raise( + exc=Call( + func=Name(id='NotImplementedError', ctx=Load()), + args=[ + Name(id='class_', ctx=Load())], + keywords=[]))])])])])])], + decorator_list=[], + returns=Name(id='Extended', ctx=Load())), + FunctionDef( + name='_deserialize_to_dataclass', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='U', ctx=Load()), + ctx=Load())), + arg( + arg='decoded', + annotation=Name(id='Simple', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assert( + test=Call( + func=Name(id='is_dataclass', ctx=Load()), + args=[ + Name(id='cls', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hints', ctx=Store())], + value=Call( + func=Name(id='get_type_hints', ctx=Load()), + args=[ + Name(id='cls', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='target_fields', ctx=Store())], + value=Call( + func=Name(id='fields', ctx=Load()), + args=[ + Name(id='cls', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='decoded', ctx=Load()), + Name(id='bytes', ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Call( + func=Name(id='RLPDecodingError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='got `bytes` while decoding `'), + FormattedValue( + value=Attribute( + value=Name(id='cls', ctx=Load()), + attr='__name__', + ctx=Load()), + conversion=-1), + Constant(value='`')])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='target_fields', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='decoded', ctx=Load())], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='name', ctx=Store())], + value=Attribute( + value=Name(id='cls', ctx=Load()), + attr='__name__', + ctx=Load())), + Assign( + targets=[ + Name(id='actual', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='decoded', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='expected', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='target_fields', ctx=Load())], + keywords=[])), + Raise( + exc=Call( + func=Name(id='RLPDecodingError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='`'), + FormattedValue( + value=Name(id='name', ctx=Load()), + conversion=-1), + Constant(value='` needs '), + FormattedValue( + value=Name(id='expected', ctx=Load()), + conversion=-1), + Constant(value=' field(s), but got '), + FormattedValue( + value=Name(id='actual', ctx=Load()), + conversion=-1), + Constant(value=' instead')])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='values', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='str', ctx=Load()), + Name(id='Any', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='value', ctx=Store()), + Name(id='target_field', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='zip', ctx=Load()), + args=[ + Name(id='decoded', ctx=Load()), + Name(id='target_fields', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='resolved_type', ctx=Store())], + value=Subscript( + value=Name(id='hints', ctx=Load()), + slice=Attribute( + value=Name(id='target_field', ctx=Load()), + attr='name', + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Attribute( + value=Name(id='target_field', ctx=Load()), + attr='name', + ctx=Load()), + ctx=Store())], + value=Call( + func=Name(id='_deserialize_to', ctx=Load()), + args=[ + Name(id='resolved_type', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='cls', ctx=Load()), + args=[], + keywords=[ + keyword( + value=Name(id='values', ctx=Load()))])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='result', ctx=Load()), + Name(id='cls', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='cast', ctx=Load()), + args=[ + Name(id='U', ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='U', ctx=Load())), + FunctionDef( + name='_deserialize_to_bool', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='Simple', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Return( + value=Constant(value=False))], + orelse=[ + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'\x01')]), + body=[ + Return( + value=Constant(value=True))], + orelse=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))])])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='_deserialize_to_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='class_', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='FixedBytes', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='Simple', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='bytes', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Try( + body=[ + Return( + value=Call( + func=Name(id='class_', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + name='e', + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()), + cause=Name(id='e', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='FixedBytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='_deserialize_to_uint', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='class_', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='FixedUnsigned', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='decoded', + annotation=Name(id='Simple', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='decoded', ctx=Load()), + Name(id='bytes', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Try( + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='class_', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='decoded', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + name='e', + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()), + cause=Name(id='e', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='FixedUnsigned', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='_deserialize_to_annotation', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='annotation', + annotation=Name(id='object', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Simple', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='origin', ctx=Store())], + value=Call( + func=Name(id='get_origin', ctx=Load()), + args=[ + Name(id='annotation', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='origin', ctx=Load()), + ops=[ + Is()], + comparators=[ + Name(id='Union', ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='_deserialize_to_union', ctx=Load()), + args=[ + Name(id='annotation', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='origin', ctx=Load()), + ops=[ + In()], + comparators=[ + Tuple( + elts=[ + Name(id='Tuple', ctx=Load()), + Name(id='tuple', ctx=Load())], + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='_deserialize_to_tuple', ctx=Load()), + args=[ + Name(id='annotation', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='origin', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Name(id='annotation', ctx=Load())], + keywords=[]))], + orelse=[ + Raise( + exc=Call( + func=Name(id='NotImplementedError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='RLP non-type '), + FormattedValue( + value=Name(id='origin', ctx=Load()), + conversion=114)])], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Extended', ctx=Load())), + FunctionDef( + name='_deserialize_to_union', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='annotation', + annotation=Name(id='object', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Simple', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='arguments', ctx=Store())], + value=Call( + func=Name(id='get_args', ctx=Load()), + args=[ + Name(id='annotation', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='successes', ctx=Store())], + value=List(elts=[], ctx=Load())), + Assign( + targets=[ + Name(id='failures', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='argument', ctx=Store()), + iter=Name(id='arguments', ctx=Load()), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='success', ctx=Store())], + value=Call( + func=Name(id='_deserialize_to', ctx=Load()), + args=[ + Name(id='argument', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='Exception', ctx=Load()), + name='e', + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='failures', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='e', ctx=Load())], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='successes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='success', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='successes', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Return( + value=Subscript( + value=Name(id='successes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + orelse=[ + If( + test=UnaryOp( + op=Not(), + operand=Name(id='successes', ctx=Load())), + body=[ + Raise( + exc=Call( + func=Name(id='RLPDecodingError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='no matching union variant\n'), + FormattedValue( + value=Name(id='failures', ctx=Load()), + conversion=114)])], + keywords=[]))], + orelse=[ + Raise( + exc=Call( + func=Name(id='RLPDecodingError', ctx=Load()), + args=[ + Constant(value='multiple matching union variants')], + keywords=[]))])])], + decorator_list=[], + returns=Name(id='Extended', ctx=Load())), + FunctionDef( + name='_deserialize_to_tuple', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='annotation', + annotation=Name(id='object', ctx=Load())), + arg( + arg='values', + annotation=Name(id='Simple', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='values', ctx=Load()), + Name(id='bytes', ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='arguments', ctx=Store())], + value=Call( + func=Name(id='list', ctx=Load()), + args=[ + Call( + func=Name(id='get_args', ctx=Load()), + args=[ + Name(id='annotation', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Subscript( + value=Name(id='arguments', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + ops=[ + Is()], + comparators=[ + Name(id='Ellipsis', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='arguments', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='fill_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='values', ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='arguments', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='arguments', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='list', ctx=Load()), + args=[ + Name(id='arguments', ctx=Load())], + keywords=[]), + op=Add(), + right=BinOp( + left=List( + elts=[ + Subscript( + value=Name(id='arguments', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load()), + op=Mult(), + right=Name(id='fill_count', ctx=Load()))))], + orelse=[]), + Assign( + targets=[ + Name(id='decoded', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Tuple( + elts=[ + Name(id='argument', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='zip', ctx=Load()), + args=[ + Name(id='arguments', ctx=Load()), + Name(id='values', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='decoded', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Name(id='_deserialize_to', ctx=Load()), + args=[ + Name(id='argument', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='decoded', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Extended', ctx=Load()), + ctx=Load())), + FunctionDef( + name='decode_to_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='encoded_bytes', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decodes a rlp encoded byte stream assuming that the decoded data\n should be of type `bytes`.\n\n Parameters\n ----------\n encoded_bytes :\n RLP encoded byte stream.\n\n Returns\n -------\n decoded : `ethereum.base_types.Bytes`\n RLP decoded Bytes data\n ')), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded_bytes', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + Compare( + left=Subscript( + value=Name(id='encoded_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=128)])]), + body=[ + Return( + value=Name(id='encoded_bytes', ctx=Load()))], + orelse=[ + If( + test=Compare( + left=Subscript( + value=Name(id='encoded_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Constant(value=183)]), + body=[ + Assign( + targets=[ + Name(id='len_raw_data', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='encoded_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=Sub(), + right=Constant(value=128))), + If( + test=Compare( + left=Name(id='len_raw_data', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded_bytes', ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='raw_data', ctx=Store())], + value=Subscript( + value=Name(id='encoded_bytes', ctx=Load()), + slice=Slice( + lower=Constant(value=1), + upper=BinOp( + left=Constant(value=1), + op=Add(), + right=Name(id='len_raw_data', ctx=Load()))), + ctx=Load())), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='len_raw_data', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + Compare( + left=Subscript( + value=Name(id='raw_data', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=128)])]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='raw_data', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='decoded_data_start_idx', ctx=Store())], + value=BinOp( + left=BinOp( + left=Constant(value=1), + op=Add(), + right=Subscript( + value=Name(id='encoded_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + op=Sub(), + right=Constant(value=183))), + If( + test=Compare( + left=BinOp( + left=Name(id='decoded_data_start_idx', ctx=Load()), + op=Sub(), + right=Constant(value=1)), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded_bytes', ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Subscript( + value=Name(id='encoded_bytes', ctx=Load()), + slice=Constant(value=1), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='len_decoded_data', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='encoded_bytes', ctx=Load()), + slice=Slice( + lower=Constant(value=1), + upper=Name(id='decoded_data_start_idx', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='len_decoded_data', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=56)]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='decoded_data_end_idx', ctx=Store())], + value=BinOp( + left=Name(id='decoded_data_start_idx', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='len_decoded_data', ctx=Load())], + keywords=[]))), + If( + test=Compare( + left=BinOp( + left=Name(id='decoded_data_end_idx', ctx=Load()), + op=Sub(), + right=Constant(value=1)), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded_bytes', ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Return( + value=Subscript( + value=Name(id='encoded_bytes', ctx=Load()), + slice=Slice( + lower=Name(id='decoded_data_start_idx', ctx=Load()), + upper=Name(id='decoded_data_end_idx', ctx=Load())), + ctx=Load()))])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='decode_to_sequence', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='encoded_sequence', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decodes a rlp encoded byte stream assuming that the decoded data\n should be of type `Sequence` of objects.\n\n Parameters\n ----------\n encoded_sequence :\n An RLP encoded Sequence.\n\n Returns\n -------\n decoded : `Sequence[RLP]`\n Sequence of objects decoded from `encoded_sequence`.\n ')), + If( + test=Compare( + left=Subscript( + value=Name(id='encoded_sequence', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Constant(value=247)]), + body=[ + Assign( + targets=[ + Name(id='len_joined_encodings', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='encoded_sequence', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=Sub(), + right=Constant(value=192))), + If( + test=Compare( + left=Name(id='len_joined_encodings', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded_sequence', ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='joined_encodings', ctx=Store())], + value=Subscript( + value=Name(id='encoded_sequence', ctx=Load()), + slice=Slice( + lower=Constant(value=1), + upper=BinOp( + left=Constant(value=1), + op=Add(), + right=Name(id='len_joined_encodings', ctx=Load()))), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='joined_encodings_start_idx', ctx=Store())], + value=BinOp( + left=BinOp( + left=Constant(value=1), + op=Add(), + right=Subscript( + value=Name(id='encoded_sequence', ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + op=Sub(), + right=Constant(value=247))), + If( + test=Compare( + left=BinOp( + left=Name(id='joined_encodings_start_idx', ctx=Load()), + op=Sub(), + right=Constant(value=1)), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded_sequence', ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Subscript( + value=Name(id='encoded_sequence', ctx=Load()), + slice=Constant(value=1), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='len_joined_encodings', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='encoded_sequence', ctx=Load()), + slice=Slice( + lower=Constant(value=1), + upper=Name(id='joined_encodings_start_idx', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='len_joined_encodings', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=56)]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='joined_encodings_end_idx', ctx=Store())], + value=BinOp( + left=Name(id='joined_encodings_start_idx', ctx=Load()), + op=Add(), + right=Name(id='len_joined_encodings', ctx=Load()))), + If( + test=Compare( + left=BinOp( + left=Name(id='joined_encodings_end_idx', ctx=Load()), + op=Sub(), + right=Constant(value=1)), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded_sequence', ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='joined_encodings', ctx=Store())], + value=Subscript( + value=Name(id='encoded_sequence', ctx=Load()), + slice=Slice( + lower=Name(id='joined_encodings_start_idx', ctx=Load()), + upper=Name(id='joined_encodings_end_idx', ctx=Load())), + ctx=Load()))]), + Return( + value=Call( + func=Name(id='decode_joined_encodings', ctx=Load()), + args=[ + Name(id='joined_encodings', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Simple', ctx=Load()), + ctx=Load())), + FunctionDef( + name='decode_joined_encodings', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='joined_encodings', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decodes `joined_encodings`, which is a concatenation of RLP encoded\n objects.\n\n Parameters\n ----------\n joined_encodings :\n concatenation of RLP encoded objects\n\n Returns\n -------\n decoded : `List[RLP]`\n A list of objects decoded from `joined_encodings`.\n ')), + Assign( + targets=[ + Name(id='decoded_sequence', ctx=Store())], + value=List(elts=[], ctx=Load())), + Assign( + targets=[ + Name(id='item_start_idx', ctx=Store())], + value=Constant(value=0)), + While( + test=Compare( + left=Name(id='item_start_idx', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='joined_encodings', ctx=Load())], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='encoded_item_length', ctx=Store())], + value=Call( + func=Name(id='decode_item_length', ctx=Load()), + args=[ + Subscript( + value=Name(id='joined_encodings', ctx=Load()), + slice=Slice( + lower=Name(id='item_start_idx', ctx=Load())), + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=BinOp( + left=Name(id='item_start_idx', ctx=Load()), + op=Add(), + right=Name(id='encoded_item_length', ctx=Load())), + op=Sub(), + right=Constant(value=1)), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='joined_encodings', ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='encoded_item', ctx=Store())], + value=Subscript( + value=Name(id='joined_encodings', ctx=Load()), + slice=Slice( + lower=Name(id='item_start_idx', ctx=Load()), + upper=BinOp( + left=Name(id='item_start_idx', ctx=Load()), + op=Add(), + right=Name(id='encoded_item_length', ctx=Load()))), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='decoded_sequence', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Name(id='decode', ctx=Load()), + args=[ + Name(id='encoded_item', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Name(id='item_start_idx', ctx=Store()), + op=Add(), + value=Name(id='encoded_item_length', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='decoded_sequence', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Simple', ctx=Load()), + ctx=Load())), + FunctionDef( + name='decode_item_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='encoded_data', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Find the length of the rlp encoding for the first object in the\n encoded sequence.\n Here `encoded_data` refers to concatenation of rlp encoding for each\n item in a sequence.\n\n NOTE - This is a helper function not described in the spec. It was\n introduced as the spec doesn't discuss about decoding the RLP encoded\n data.\n\n Parameters\n ----------\n encoded_data :\n RLP encoded data for a sequence of objects.\n\n Returns\n -------\n rlp_length : `int`\n ")), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded_data', ctx=Load())], + keywords=[]), + ops=[ + LtE()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='first_rlp_byte', ctx=Store())], + value=Subscript( + value=Name(id='encoded_data', ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + Assign( + targets=[ + Name(id='length_length', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='decoded_data_length', ctx=Store())], + value=Constant(value=0)), + If( + test=Compare( + left=Name(id='first_rlp_byte', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=128)]), + body=[ + Return( + value=Constant(value=1))], + orelse=[ + If( + test=Compare( + left=Name(id='first_rlp_byte', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Constant(value=183)]), + body=[ + Assign( + targets=[ + Name(id='decoded_data_length', ctx=Store())], + value=BinOp( + left=Name(id='first_rlp_byte', ctx=Load()), + op=Sub(), + right=Constant(value=128)))], + orelse=[ + If( + test=Compare( + left=Name(id='first_rlp_byte', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Constant(value=191)]), + body=[ + Assign( + targets=[ + Name(id='length_length', ctx=Store())], + value=BinOp( + left=Name(id='first_rlp_byte', ctx=Load()), + op=Sub(), + right=Constant(value=183))), + If( + test=Compare( + left=Name(id='length_length', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded_data', ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Subscript( + value=Name(id='encoded_data', ctx=Load()), + slice=Constant(value=1), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='decoded_data_length', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='encoded_data', ctx=Load()), + slice=Slice( + lower=Constant(value=1), + upper=BinOp( + left=Constant(value=1), + op=Add(), + right=Name(id='length_length', ctx=Load()))), + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='first_rlp_byte', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Constant(value=247)]), + body=[ + Assign( + targets=[ + Name(id='decoded_data_length', ctx=Store())], + value=BinOp( + left=Name(id='first_rlp_byte', ctx=Load()), + op=Sub(), + right=Constant(value=192)))], + orelse=[ + If( + test=Compare( + left=Name(id='first_rlp_byte', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Name(id='length_length', ctx=Store())], + value=BinOp( + left=Name(id='first_rlp_byte', ctx=Load()), + op=Sub(), + right=Constant(value=247))), + If( + test=Compare( + left=Name(id='length_length', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded_data', ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Subscript( + value=Name(id='encoded_data', ctx=Load()), + slice=Constant(value=1), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='RLPDecodingError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='decoded_data_length', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='encoded_data', ctx=Load()), + slice=Slice( + lower=Constant(value=1), + upper=BinOp( + left=Constant(value=1), + op=Add(), + right=Name(id='length_length', ctx=Load()))), + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])])])])]), + Return( + value=BinOp( + left=BinOp( + left=Constant(value=1), + op=Add(), + right=Name(id='length_length', ctx=Load())), + op=Add(), + right=Name(id='decoded_data_length', ctx=Load())))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='rlp_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Name(id='Extended', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the keccak-256 hash of the rlp encoding of the passed in data.\n\n Parameters\n ----------\n data :\n The data for which we need the rlp hash.\n\n Returns\n -------\n hash : `Hash32`\n The rlp hash of the passed in data.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Name(id='encode', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/rlp.v b/coq/ethereum/rlp.v new file mode 100644 index 0000000000..65bcfe9f56 --- /dev/null +++ b/coq/ethereum/rlp.v @@ -0,0 +1,359 @@ +(* Generated *) +(* +.. _rlp: + +Recursive Length Prefix (RLP) Encoding +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Defines the serialization and deserialization format used throughout Ethereum. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.exceptions. + +Definition encode (raw_data : Extended) : M Bytes := + (* + Encodes `raw_data` into a sequence of bytes using RLP. + + Parameters + ---------- + raw_data : + A `Bytes`, `Uint`, `Uint256` or sequence of `RLP` encodable + objects. + + Returns + ------- + encoded : `ethereum.base_types.Bytes` + The RLP encoded bytes representing `raw_data`. + *) + (* TODO statement *) + M.pure tt. + +Definition encode_bytes (raw_bytes : Bytes) : M Bytes := + (* + Encodes `raw_bytes`, a sequence of bytes, using RLP. + + Parameters + ---------- + raw_bytes : + Bytes to encode with RLP. + + Returns + ------- + encoded : `ethereum.base_types.Bytes` + The RLP encoded bytes representing `raw_bytes`. + *) + do* M.assign "len_raw_data" [[ + M.get_local ~(| "len" |) ~(| + raw_bytes + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_sequence (raw_sequence : (* TODO type *)) : M Bytes := + (* + Encodes a list of RLP encodable objects (`raw_sequence`) using RLP. + + Parameters + ---------- + raw_sequence : + Sequence of RLP encodable objects. + + Returns + ------- + encoded : `ethereum.base_types.Bytes` + The RLP encoded bytes representing `raw_sequence`. + *) + do* M.assign "joined_encodings" [[ + M.get_local ~(| "get_joined_encodings" |) ~(| + raw_sequence + |) in + ]] in + do* M.assign "len_joined_encodings" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "joined_encodings" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_joined_encodings (raw_sequence : (* TODO type *)) : M Bytes := + (* + Obtain concatenation of rlp encoding for each item in the sequence + raw_sequence. + + Parameters + ---------- + raw_sequence : + Sequence to encode with RLP. + + Returns + ------- + joined_encodings : `ethereum.base_types.Bytes` + The concatenated RLP encoded bytes for each item in sequence + raw_sequence. + *) + (* TODO statement *) + M.pure tt. + +Definition decode (encoded_data : Bytes) : M Simple := + (* + Decodes an integer, byte sequence, or list of RLP encodable objects + from the byte sequence `encoded_data`, using RLP. + + Parameters + ---------- + encoded_data : + A sequence of bytes, in RLP form. + + Returns + ------- + decoded_data : `RLP` + Object decoded from `encoded_data`. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition decode_to (cls : (* TODO type *)) (encoded_data : Bytes) : M U := + (* + Decode the bytes in `encoded_data` to an object of type `cls`. `cls` can be + a `Bytes` subclass, a dataclass, `Uint`, `U256` or `Tuple[cls]`. + + Parameters + ---------- + cls: `Type[U]` + The type to decode to. + encoded_data : + A sequence of bytes, in RLP form. + + Returns + ------- + decoded_data : `U` + Object decoded from `encoded_data`. + *) + do* M.assign "decoded" [[ + M.get_local ~(| "decode" |) ~(| + encoded_data + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition _deserialize_to (class_ : (* TODO type *)) (value : Simple) : M U := + (* TODO statement *) + M.pure tt. + +Definition _deserialize_to (class_ : object) (value : Simple) : M Extended := + (* TODO statement *) + M.pure tt. + +Definition _deserialize_to (class_ : object) (value : Simple) : M Extended := + (* TODO statement *) + M.pure tt. + +Definition _deserialize_to_dataclass (cls : (* TODO type *)) (decoded : Simple) : M U := + (* TODO statement *) + do* M.assign "hints" [[ + typing.get_type_hints ~(| + cls + |) in + ]] in + do* M.assign "target_fields" [[ + dataclasses.fields ~(| + cls + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "result" [[ + cls ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _deserialize_to_bool (value : Simple) : M bool := + (* TODO statement *) + M.pure tt. + +Definition _deserialize_to_bytes (class_ : (* TODO type *)) (value : Simple) : M (* TODO type *) := + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _deserialize_to_uint (class_ : (* TODO type *)) (decoded : Simple) : M (* TODO type *) := + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _deserialize_to_annotation (annotation : object) (value : Simple) : M Extended := + do* M.assign "origin" [[ + typing.get_origin ~(| + annotation + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition _deserialize_to_union (annotation : object) (value : Simple) : M Extended := + do* M.assign "arguments" [[ + typing.get_args ~(| + annotation + |) in + ]] in + do* M.assign "successes" [[ + (* TODO expression *) in + ]] in + do* M.assign "failures" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _deserialize_to_tuple (annotation : object) (values : Simple) : M (* TODO type *) := + (* TODO statement *) + do* M.assign "arguments" [[ + M.get_local ~(| "list" |) ~(| + typing.get_args ~(| + annotation + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "decoded" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition decode_to_bytes (encoded_bytes : Bytes) : M Bytes := + (* + Decodes a rlp encoded byte stream assuming that the decoded data + should be of type `bytes`. + + Parameters + ---------- + encoded_bytes : + RLP encoded byte stream. + + Returns + ------- + decoded : `ethereum.base_types.Bytes` + RLP decoded Bytes data + *) + (* TODO statement *) + M.pure tt. + +Definition decode_to_sequence (encoded_sequence : Bytes) : M (* TODO type *) := + (* + Decodes a rlp encoded byte stream assuming that the decoded data + should be of type `Sequence` of objects. + + Parameters + ---------- + encoded_sequence : + An RLP encoded Sequence. + + Returns + ------- + decoded : `Sequence[RLP]` + Sequence of objects decoded from `encoded_sequence`. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition decode_joined_encodings (joined_encodings : Bytes) : M (* TODO type *) := + (* + Decodes `joined_encodings`, which is a concatenation of RLP encoded + objects. + + Parameters + ---------- + joined_encodings : + concatenation of RLP encoded objects + + Returns + ------- + decoded : `List[RLP]` + A list of objects decoded from `joined_encodings`. + *) + do* M.assign "decoded_sequence" [[ + (* TODO expression *) in + ]] in + do* M.assign "item_start_idx" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition decode_item_length (encoded_data : Bytes) : M int := + (* + Find the length of the rlp encoding for the first object in the + encoded sequence. + Here `encoded_data` refers to concatenation of rlp encoding for each + item in a sequence. + + NOTE - This is a helper function not described in the spec. It was + introduced as the spec doesn't discuss about decoding the RLP encoded + data. + + Parameters + ---------- + encoded_data : + RLP encoded data for a sequence of objects. + + Returns + ------- + rlp_length : `int` + *) + (* TODO statement *) + do* M.assign "first_rlp_byte" [[ + (* TODO expression *) in + ]] in + do* M.assign "length_length" [[ + 0 in + ]] in + do* M.assign "decoded_data_length" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition rlp_hash (data : Extended) : M Hash32 := + (* + Obtain the keccak-256 hash of the rlp encoding of the passed in data. + + Parameters + ---------- + data : + The data for which we need the rlp hash. + + Returns + ------- + hash : `Hash32` + The rlp hash of the passed in data. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/__init__.ast b/coq/ethereum/shanghai/__init__.ast new file mode 100644 index 0000000000..b602d6d44d --- /dev/null +++ b/coq/ethereum/shanghai/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe Shanghai fork brings staking withdrawals to the execution layer, adds a\npush-zero EVM instruction, limits the maximum size of initialization\nbytecode, and deprecates the self-destruct EVM instruction.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByTimestamp')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByTimestamp', ctx=Load()), + args=[ + Constant(value=1681338455)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/__init__.v b/coq/ethereum/shanghai/__init__.v new file mode 100644 index 0000000000..1dd362e7f8 --- /dev/null +++ b/coq/ethereum/shanghai/__init__.v @@ -0,0 +1,8 @@ +(* Generated *) +(* +The Shanghai fork brings staking withdrawals to the execution layer, adds a +push-zero EVM instruction, limits the maximum size of initialization +bytecode, and deprecates the self-destruct EVM instruction. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/shanghai/blocks.ast b/coq/ethereum/shanghai/blocks.ast new file mode 100644 index 0000000000..4c782a49cf --- /dev/null +++ b/coq/ethereum/shanghai/blocks.ast @@ -0,0 +1,272 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='LegacyTransaction')], + level=1), + ClassDef( + name='Withdrawal', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Withdrawals that have been validated on the consensus layer.\n ')), + AnnAssign( + target=Name(id='index', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='validator_index', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='amount', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='prev_randao', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='withdrawals_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='withdrawals', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Withdrawal', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='succeeded', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/blocks.v b/coq/ethereum/shanghai/blocks.v new file mode 100644 index 0000000000..110c8f0391 --- /dev/null +++ b/coq/ethereum/shanghai/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.shanghai.fork_types. +Require ethereum.shanghai.transactions. diff --git a/coq/ethereum/shanghai/bloom.ast b/coq/ethereum/shanghai/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/shanghai/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/bloom.v b/coq/ethereum/shanghai/bloom.v new file mode 100644 index 0000000000..3fe3ba02e8 --- /dev/null +++ b/coq/ethereum/shanghai/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.shanghai.blocks. +Require ethereum.shanghai.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/exceptions.ast b/coq/ethereum/shanghai/exceptions.ast new file mode 100644 index 0000000000..a61ee25448 --- /dev/null +++ b/coq/ethereum/shanghai/exceptions.ast @@ -0,0 +1,72 @@ +Module( + body=[ + Expr( + value=Constant(value='\nExceptions specific to this fork.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Final')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidTransaction')], + level=0), + ClassDef( + name='TransactionTypeError', + bases=[ + Name(id='InvalidTransaction', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Unknown [EIP-2718] transaction type byte.\n\n [EIP-2718]: https://eips.ethereum.org/EIPS/eip-2718\n ')), + AnnAssign( + target=Name(id='transaction_type', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n The type byte of the transaction that caused the error.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='transaction_type', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='unknown transaction type `'), + FormattedValue( + value=Name(id='transaction_type', ctx=Load()), + conversion=-1), + Constant(value='`')])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='transaction_type', + ctx=Store())], + value=Name(id='transaction_type', ctx=Load()))], + decorator_list=[])], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/exceptions.v b/coq/ethereum/shanghai/exceptions.v new file mode 100644 index 0000000000..9a313f6d0e --- /dev/null +++ b/coq/ethereum/shanghai/exceptions.v @@ -0,0 +1,7 @@ +(* Generated *) +(* +Exceptions specific to this fork. +*) + +Require typing. +Require ethereum.exceptions. diff --git a/coq/ethereum/shanghai/fork.ast b/coq/ethereum/shanghai/fork.ast new file mode 100644 index 0000000000..0a012844d1 --- /dev/null +++ b/coq/ethereum/shanghai/fork.ast @@ -0,0 +1,3253 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt'), + alias(name='Withdrawal')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='process_withdrawal'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_ACCESS_LIST_ADDRESS_COST'), + alias(name='TX_ACCESS_LIST_STORAGE_KEY_COST'), + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='AccessListTransaction'), + alias(name='FeeMarketTransaction'), + alias(name='LegacyTransaction'), + alias(name='Transaction'), + alias(name='decode_transaction'), + alias(name='encode_transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.gas', + names=[ + alias(name='init_code_cost')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='MAX_CODE_SIZE'), + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='ELASTICITY_MULTIPLIER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='EMPTY_OMMER_HASH', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List(elts=[], ctx=Load())], + keywords=[])], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Tuple(elts=[], ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='prev_randao', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='chain', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='withdrawals', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='withdrawals_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='withdrawals_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_base_fee_per_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the base fee per gas for the block.\n\n Parameters\n ----------\n block_gas_limit :\n Gas limit of the block for which the base fee is being calculated.\n parent_gas_limit :\n Gas limit of the parent block.\n parent_gas_used :\n Gas used in the parent block.\n parent_base_fee_per_gas :\n Base fee per gas of the parent block.\n\n Returns\n -------\n base_fee_per_gas : `Uint`\n Base fee per gas for the block.\n ')), + Assign( + targets=[ + Name(id='parent_gas_target', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='ELASTICITY_MULTIPLIER', ctx=Load()))), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Name(id='block_gas_limit', ctx=Load()), + Name(id='parent_gas_limit', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='parent_gas_used', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='parent_gas_target', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=Name(id='parent_base_fee_per_gas', ctx=Load()))], + orelse=[ + If( + test=Compare( + left=Name(id='parent_gas_used', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='parent_gas_target', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='gas_used_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_used', ctx=Load()), + op=Sub(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='parent_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Mult(), + right=Name(id='gas_used_delta', ctx=Load()))), + Assign( + targets=[ + Name(id='target_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='base_fee_per_gas_delta', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=Name(id='target_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Load())), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Add(), + right=Name(id='base_fee_per_gas_delta', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='gas_used_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_target', ctx=Load()), + op=Sub(), + right=Name(id='parent_gas_used', ctx=Load()))), + Assign( + targets=[ + Name(id='parent_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Mult(), + right=Name(id='gas_used_delta', ctx=Load()))), + Assign( + targets=[ + Name(id='target_fee_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='parent_gas_target', ctx=Load()))), + Assign( + targets=[ + Name(id='base_fee_per_gas_delta', ctx=Store())], + value=BinOp( + left=Name(id='target_fee_gas_delta', ctx=Load()), + op=FloorDiv(), + right=Name(id='BASE_FEE_MAX_CHANGE_DENOMINATOR', ctx=Load()))), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=BinOp( + left=Name(id='parent_base_fee_per_gas', ctx=Load()), + op=Sub(), + right=Name(id='base_fee_per_gas_delta', ctx=Load())))])]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='expected_base_fee_per_gas', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='expected_base_fee_per_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_base_fee_per_gas', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='expected_base_fee_per_gas', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'\x00\x00\x00\x00\x00\x00\x00\x00')]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='EMPTY_OMMER_HASH', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n base_fee_per_gas :\n The block base fee.\n gas_available :\n The gas remaining in the block.\n chain_id :\n The ID of the current chain.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n effective_gas_price :\n The price to charge for gas when the transaction is executed.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='base_fee_per_gas', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='priority_fee_per_gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + op=Sub(), + right=Name(id='base_fee_per_gas', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='effective_gas_price', ctx=Store())], + value=BinOp( + left=Name(id='priority_fee_per_gas', ctx=Load()), + op=Add(), + right=Name(id='base_fee_per_gas', ctx=Load())))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='base_fee_per_gas', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='effective_gas_price', ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))]), + Return( + value=Tuple( + elts=[ + Name(id='sender_address', ctx=Load()), + Name(id='effective_gas_price', ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='error', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n error :\n Error in the top level frame of the transaction, if any.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='succeeded', + value=Compare( + left=Name(id='error', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)])), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='receipt', ctx=Load())], + keywords=[])))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='receipt', ctx=Load())], + keywords=[])))], + orelse=[ + Return( + value=Name(id='receipt', ctx=Load()))])])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Receipt', ctx=Load())], + ctx=Load()), + ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n withdrawals_root : `ethereum.fork_types.Root`\n Trie root of all the withdrawals in the block.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='withdrawals_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='base_fee_per_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='prev_randao', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='withdrawals', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Withdrawal', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n base_fee_per_gas :\n Base fee per gas of within the block.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n prev_randao :\n The previous randao from the beacon chain.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n chain_id :\n ID of the executing chain.\n withdrawals :\n Withdrawals to be processed in the current block.\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Receipt', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='withdrawals_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Withdrawal', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Call( + func=Name(id='map', ctx=Load()), + args=[ + Name(id='decode_transaction', ctx=Load()), + Name(id='transactions', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Call( + func=Name(id='encode_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='sender_address', ctx=Store()), + Name(id='effective_gas_price', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='base_fee_per_gas', ctx=Load()), + Name(id='gas_available', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='base_fee_per_gas', + value=Name(id='base_fee_per_gas', ctx=Load())), + keyword( + arg='gas_price', + value=Name(id='effective_gas_price', ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='prev_randao', + value=Name(id='prev_randao', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='chain_id', + value=Name(id='chain_id', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store()), + Name(id='error', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='error', ctx=Load()), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='wd', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='withdrawals', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='withdrawals_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='wd', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='process_withdrawal', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='wd', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='wd', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='wd', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='withdrawals_trie', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='max_gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='max_gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())))]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='max_gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='effective_gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='effective_gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='preaccessed_addresses', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='preaccessed_storage_keys', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Tuple( + elts=[ + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='address', ctx=Store()), + Name(id='keys', ctx=Store())], + ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='keys', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='preaccessed_storage_keys', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Name(id='address', ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[ + keyword( + arg='preaccessed_addresses', + value=Call( + func=Name(id='frozenset', ctx=Load()), + args=[ + Name(id='preaccessed_addresses', ctx=Load())], + keywords=[])), + keyword( + arg='preaccessed_storage_keys', + value=Call( + func=Name(id='frozenset', ctx=Load()), + args=[ + Name(id='preaccessed_storage_keys', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='priority_fee_per_gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='env', ctx=Load()), + attr='gas_price', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='env', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Name(id='priority_fee_per_gas', ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + If( + test=Compare( + left=Name(id='coinbase_balance_after_mining_fee', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]))], + orelse=[])]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='error', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='MAX_CODE_SIZE', ctx=Load()))])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=BinOp( + left=Name(id='TX_CREATE_COST', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='init_code_cost', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])], + keywords=[])))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Assign( + targets=[ + Name(id='access_list_cost', ctx=Store())], + value=Constant(value=0)), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Tuple( + elts=[ + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='_address', ctx=Store()), + Name(id='keys', ctx=Store())], + ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load()), + body=[ + AugAssign( + target=Name(id='access_list_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_ACCESS_LIST_ADDRESS_COST', ctx=Load())), + AugAssign( + target=Name(id='access_list_cost', ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='keys', ctx=Load())], + keywords=[]), + op=Mult(), + right=Name(id='TX_ACCESS_LIST_STORAGE_KEY_COST', ctx=Load())))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load())), + op=Add(), + right=Name(id='access_list_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=28)])]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash_pre155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='chain_id_x2', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=36)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[])), + op=Sub(), + right=Name(id='chain_id_x2', ctx=Load())), + Call( + func=Name(id='signing_hash_155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])], + keywords=[]))])], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='y_parity', + ctx=Load()), + Call( + func=Name(id='signing_hash_2930', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='y_parity', + ctx=Load()), + Call( + func=Name(id='signing_hash_1559', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])])]), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash_pre155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='LegacyTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a legacy (pre EIP 155) signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='LegacyTransaction', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 155 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n The id of the current chain.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='chain_id', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_2930', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='AccessListTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 2930 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load())], + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_1559', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='FeeMarketTransaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 1559 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_priority_fee_per_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='max_fee_per_gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='access_list', + ctx=Load())], + ctx=Load())], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/fork.v b/coq/ethereum/shanghai/fork.v new file mode 100644 index 0000000000..60c0db882a --- /dev/null +++ b/coq/ethereum/shanghai/fork.v @@ -0,0 +1,727 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.shanghai.__init__. +Require ethereum.shanghai.blocks. +Require ethereum.shanghai.bloom. +Require ethereum.shanghai.fork_types. +Require ethereum.shanghai.state. +Require ethereum.shanghai.transactions. +Require ethereum.shanghai.trie. +Require ethereum.shanghai.utils.message. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + (* TODO statement *) + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "base_fee_per_gas" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "prev_randao" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| chain, "chain_id" |), + M.get_field ~(| block, "withdrawals" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_base_fee_per_gas (block_gas_limit : Uint) (parent_gas_limit : Uint) (parent_gas_used : Uint) (parent_base_fee_per_gas : Uint) : M Uint := + (* + 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. + *) + do* M.assign "parent_gas_target" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + (* TODO statement *) + do* M.assign "expected_base_fee_per_gas" [[ + M.get_local ~(| "calculate_base_fee_per_gas" |) ~(| + M.get_field ~(| header, "gas_limit" |), + M.get_field ~(| parent_header, "gas_limit" |), + M.get_field ~(| parent_header, "gas_used" |), + M.get_field ~(| parent_header, "base_fee_per_gas" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (base_fee_per_gas : Uint) (gas_available : Uint) (chain_id : U64) : M (* TODO type *) := + (* + 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. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (error : (* TODO type *)) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (base_fee_per_gas : Uint) (block_gas_limit : Uint) (block_time : U256) (prev_randao : Bytes32) (transactions : (* TODO type *)) (chain_id : U64) (withdrawals : (* TODO type *)) : M ApplyBodyOutput := + (* + Executes a block. + + Many of the contents of a block are stored in data structures called + tries. There is a transactions trie which is similar to a ledger of the + transactions stored in the current block. There is also a receipts trie + which stores the results of executing a transaction, like the post state + and gas used. This function creates and executes the block that is to be + added to the chain. + + Parameters + ---------- + state : + Current account state. + block_hashes : + List of hashes of the previous 256 blocks in the order of + increasing block number. + coinbase : + Address of account which receives block reward and transaction fees. + block_number : + Position of the block within the chain. + base_fee_per_gas : + Base fee per gas of within the block. + block_gas_limit : + Initial amount of gas available for execution in this block. + block_time : + Time the block was produced, measured in seconds since the epoch. + prev_randao : + The previous randao from the beacon chain. + transactions : + Transactions included in the block. + ommers : + Headers of ancestor blocks which are not direct parents (formerly + uncles.) + chain_id : + ID of the executing chain. + withdrawals : + Withdrawals to be processed in the current block. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "effective_gas_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "preaccessed_addresses" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "preaccessed_storage_keys" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "preaccessed_addresses" |), "add" |) ~(| + M.get_field ~(| env, "coinbase" |) + |) ]] in + (* TODO statement *) + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "priority_fee_per_gas" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "access_list_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_pre155 (tx : LegacyTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_155 (tx : LegacyTransaction) (chain_id : U64) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_2930 (tx : AccessListTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_1559 (tx : FeeMarketTransaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/fork_types.ast b/coq/ethereum/shanghai/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/shanghai/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/fork_types.v b/coq/ethereum/shanghai/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/shanghai/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/state.ast b/coq/ethereum/shanghai/state.ast new file mode 100644 index 0000000000..5d6a77e15c --- /dev/null +++ b/coq/ethereum/shanghai/state.ast @@ -0,0 +1,1710 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Withdrawal')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='created_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='set', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mark_account_created', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Mark an account as having been created in the current transaction.\n This information is used by `get_storage_original()` to handle an obscure\n edgecase.\n\n The marker is not removed even if the account creation reverts. Since the\n account cannot have had code prior to its creation and can't call\n `get_storage_original()`, this is harmless.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account that has been created.\n ")), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has zero nonce, empty code and zero balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_empty : `bool`\n True if if an account has zero nonce, empty code and zero balance,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_exists_and_is_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists and has zero nonce, empty code and zero\n balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n exists_and_is_empty : `bool`\n True if an account exists and has zero nonce, empty code and zero\n balance, False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='account', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_alive', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether is an account is both in the state and non empty.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_alive : `bool`\n True if the account is alive.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[ + Return( + value=UnaryOp( + op=Not(), + operand=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])])))])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_withdrawal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='wd', + annotation=Name(id='Withdrawal', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increase the balance of the withdrawing account.\n ')), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=BinOp( + left=Attribute( + value=Name(id='wd', ctx=Load()), + attr='amount', + ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=9))], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='wd', ctx=Load()), + attr='address', + ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage_original', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the original value in a storage slot i.e. the value before the current\n transaction began. This function reads the value from the snapshots taken\n before executing the transaction.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to read the value from.\n key:\n Key of the storage slot.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='_', ctx=Store()), + Name(id='original_trie', ctx=Store())], + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + Assign( + targets=[ + Name(id='original_account_trie', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='original_trie', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='original_account_trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='original_account_trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[]))]), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='original_value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='original_value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/state.v b/coq/ethereum/shanghai/state.v new file mode 100644 index 0000000000..05d78ff05f --- /dev/null +++ b/coq/ethereum/shanghai/state.v @@ -0,0 +1,606 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.shanghai.blocks. +Require ethereum.shanghai.fork_types. +Require ethereum.shanghai.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition mark_account_created (state : State) (address : Address) : M unit := + (* + Mark an account as having been created in the current transaction. + This information is used by `get_storage_original()` to handle an obscure + edgecase. + + The marker is not removed even if the account creation reverts. Since the + account cannot have had code prior to its creation and can't call + `get_storage_original()`, this is harmless. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account that has been created. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "created_accounts" |), "add" |) ~(| + address + |) ]] in + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_empty (state : State) (address : Address) : M bool := + (* + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition account_exists_and_is_empty (state : State) (address : Address) : M bool := + (* + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_alive (state : State) (address : Address) : M bool := + (* + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition process_withdrawal (state : State) (wd : Withdrawal) : M unit := + (* + Increase the balance of the withdrawing account. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + M.get_field ~(| wd, "address" |), + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition get_storage_original (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get the original value in a storage slot i.e. the value before the current + transaction began. This function reads the value from the snapshots taken + before executing the transaction. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to read the value from. + key: + Key of the storage slot. + *) + (* TODO statement *) + (* TODO assignment *) + do* M.assign "original_account_trie" [[ + M.get_field ~(| M.get_local ~(| "original_trie" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/transactions.ast b/coq/ethereum/shanghai/transactions.ast new file mode 100644 index 0000000000..264b048f3f --- /dev/null +++ b/coq/ethereum/shanghai/transactions.ast @@ -0,0 +1,492 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='TransactionTypeError')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + Assign( + targets=[ + Name(id='TX_ACCESS_LIST_ADDRESS_COST', ctx=Store())], + value=Constant(value=2400)), + Assign( + targets=[ + Name(id='TX_ACCESS_LIST_STORAGE_KEY_COST', ctx=Store())], + value=Constant(value=1900)), + ClassDef( + name='LegacyTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='AccessListTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The transaction type added in EIP-2930 to support access lists.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='access_list', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y_parity', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='FeeMarketTransaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The transaction type added in EIP-1559.\n ')), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_priority_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='max_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='access_list', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='y_parity', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='Transaction', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Encode a transaction. Needed because non-legacy transactions aren't RLP.\n ")), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='tx', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='AccessListTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='FeeMarketTransaction', ctx=Load())], + keywords=[]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])))], + orelse=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Unable to encode transaction of type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + conversion=-1)])], + keywords=[]))])])])], + decorator_list=[], + returns=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='decode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Decode a transaction. Needed because non-legacy transactions aren't RLP.\n ")), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Name(id='AccessListTransaction', ctx=Load()), + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=2)]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Name(id='FeeMarketTransaction', ctx=Load()), + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load())], + keywords=[]))], + orelse=[ + Raise( + exc=Call( + func=Name(id='TransactionTypeError', ctx=Load()), + args=[ + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]))])])], + orelse=[ + Return( + value=Name(id='tx', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Transaction', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/transactions.v b/coq/ethereum/shanghai/transactions.v new file mode 100644 index 0000000000..5546507632 --- /dev/null +++ b/coq/ethereum/shanghai/transactions.v @@ -0,0 +1,29 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.shanghai.exceptions. +Require ethereum.shanghai.fork_types. + +Definition encode_transaction (tx : Transaction) : M (* TODO type *) := + (* + Encode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + M.pure tt. + +Definition decode_transaction (tx : (* TODO type *)) : M Transaction := + (* + Decode a transaction. Needed because non-legacy transactions aren't RLP. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/trie.ast b/coq/ethereum/shanghai/trie.ast new file mode 100644 index 0000000000..f3c7c621b1 --- /dev/null +++ b/coq/ethereum/shanghai/trie.ast @@ -0,0 +1,1646 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.paris', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt'), + alias(name='Withdrawal')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='LegacyTransaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Name(id='Withdrawal', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Receipt', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Withdrawal', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.Extended`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='LegacyTransaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Withdrawal', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/trie.v b/coq/ethereum/shanghai/trie.v new file mode 100644 index 0000000000..3b45315972 --- /dev/null +++ b/coq/ethereum/shanghai/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.Extended` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/utils/__init__.ast b/coq/ethereum/shanghai/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/shanghai/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/utils/__init__.v b/coq/ethereum/shanghai/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/shanghai/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/shanghai/utils/address.ast b/coq/ethereum/shanghai/utils/address.ast new file mode 100644 index 0000000000..1f6bd20897 --- /dev/null +++ b/coq/ethereum/shanghai/utils/address.ast @@ -0,0 +1,216 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this shanghai version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_create2_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='salt', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='call_data', + annotation=Name(id='bytearray', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created, which is\n based on the sender address, salt and the call data as well.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n salt :\n Address generation salt.\n call_data :\n The code of the new account which is to be created.\n\n Returns\n -------\n address: `ethereum.shanghai.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='preimage', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Constant(value=b'\xff'), + op=Add(), + right=Name(id='address', ctx=Load())), + op=Add(), + right=Name(id='salt', ctx=Load())), + op=Add(), + right=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='call_data', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/utils/address.v b/coq/ethereum/shanghai/utils/address.v new file mode 100644 index 0000000000..514852436f --- /dev/null +++ b/coq/ethereum/shanghai/utils/address.v @@ -0,0 +1,115 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this shanghai version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.shanghai.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition compute_create2_contract_address (address : Address) (salt : Bytes32) (call_data : bytearray) : M Address := + (* + Computes address of the new account that needs to be created, which is + based on the sender address, salt and the call data as well. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + salt : + Address generation salt. + call_data : + The code of the new account which is to be created. + + Returns + ------- + address: `ethereum.shanghai.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "preimage" [[ + (* TODO expression *) in + ]] in + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "preimage" |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/utils/hexadecimal.ast b/coq/ethereum/shanghai/utils/hexadecimal.ast new file mode 100644 index 0000000000..8ca00acafc --- /dev/null +++ b/coq/ethereum/shanghai/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to\nShanghai types.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/utils/hexadecimal.v b/coq/ethereum/shanghai/utils/hexadecimal.v new file mode 100644 index 0000000000..e674290c63 --- /dev/null +++ b/coq/ethereum/shanghai/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Shanghai types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.shanghai.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/utils/message.ast b/coq/ethereum/shanghai/utils/message.ast new file mode 100644 index 0000000000..bc7e0605fe --- /dev/null +++ b/coq/ethereum/shanghai/utils/message.ast @@ -0,0 +1,335 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this shanghai version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='FrozenSet'), + alias(name='Optional'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_static', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='preaccessed_addresses', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='preaccessed_storage_keys', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True), + Constant(value=False), + Call( + func=Name(id='frozenset', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='frozenset', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n is_static:\n if True then it prevents all state-changing operations from being\n executed.\n preaccessed_addresses:\n Addresses that should be marked as accessed prior to the message call\n preaccessed_storage_keys:\n Storage keys that should be marked as accessed prior to the message\n call\n\n Returns\n -------\n message: `ethereum.shanghai.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Assign( + targets=[ + Name(id='accessed_addresses', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='current_target', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='caller', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='accessed_addresses', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Name(id='preaccessed_addresses', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=Name(id='is_static', ctx=Load())), + keyword( + arg='accessed_addresses', + value=Name(id='accessed_addresses', ctx=Load())), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='preaccessed_storage_keys', ctx=Load())], + keywords=[])), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/utils/message.v b/coq/ethereum/shanghai/utils/message.v new file mode 100644 index 0000000000..f35544420d --- /dev/null +++ b/coq/ethereum/shanghai/utils/message.v @@ -0,0 +1,85 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this shanghai version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.shanghai.fork_types. +Require ethereum.shanghai.state. +Require ethereum.shanghai.vm. +Require ethereum.shanghai.vm.precompiled_contracts.mapping. +Require ethereum.shanghai.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) (is_static : bool) (preaccessed_addresses : (* TODO type *)) (preaccessed_storage_keys : (* TODO type *)) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + is_static: + if True then it prevents all state-changing operations from being + executed. + preaccessed_addresses: + Addresses that should be marked as accessed prior to the message call + preaccessed_storage_keys: + Storage keys that should be marked as accessed prior to the message + call + + Returns + ------- + message: `ethereum.shanghai.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + do* M.assign "accessed_addresses" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "add" |) ~(| + M.get_local ~(| "current_target" |) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "add" |) ~(| + caller + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| vm.precompiled_contracts.mapping.PRE_COMPILED_CONTRACTS, "keys" |) ~(| + + |) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "accessed_addresses" |), "update" |) ~(| + preaccessed_addresses + |) ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/__init__.ast b/coq/ethereum/shanghai/vm/__init__.ast new file mode 100644 index 0000000000..9e86a7333b --- /dev/null +++ b/coq/ethereum/shanghai/vm/__init__.ast @@ -0,0 +1,591 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty')], + level=2), + ImportFrom( + module='precompiled_contracts', + names=[ + alias(name='RIPEMD160_ADDRESS')], + level=1), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee_per_gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='prev_randao', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='is_static', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_addresses', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_storage_keys', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='return_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_addresses', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accessed_storage_keys', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Bytes32', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + If( + test=Compare( + left=Name(id='RIPEMD160_ADDRESS', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/__init__.v b/coq/ethereum/shanghai/vm/__init__.v new file mode 100644 index 0000000000..191af3aebd --- /dev/null +++ b/coq/ethereum/shanghai/vm/__init__.v @@ -0,0 +1,78 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.shanghai.blocks. +Require ethereum.shanghai.fork_types. +Require ethereum.shanghai.state. +Require ethereum.shanghai.vm.precompiled_contracts. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "touched_accounts" |), "update" |) ~(| + M.get_field ~(| child_evm, "touched_accounts" |) + |) ]] in + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "update" |) ~(| + M.get_field ~(| child_evm, "accessed_addresses" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_storage_keys" |), "update" |) ~(| + M.get_field ~(| child_evm, "accessed_storage_keys" |) + |) ]] in + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + (* TODO statement *) + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/exceptions.ast b/coq/ethereum/shanghai/vm/exceptions.ast new file mode 100644 index 0000000000..79ecb4b47d --- /dev/null +++ b/coq/ethereum/shanghai/vm/exceptions.ast @@ -0,0 +1,175 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='Revert', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised by the `REVERT` opcode.\n\n Unlike other EVM exceptions this does not result in the consumption of all\n gas.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='WriteInStaticContext', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt is made to modify the state while operating inside\n of a STATICCALL context.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfBoundsRead', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an attempt was made to read data beyond the\n boundaries of the buffer.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidParameter', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when invalid parameters are passed.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidContractPrefix', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract code starts with 0xEF.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/exceptions.v b/coq/ethereum/shanghai/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/shanghai/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/shanghai/vm/gas.ast b/coq/ethereum/shanghai/vm/gas.ast new file mode 100644 index 0000000000..8466c23f40 --- /dev/null +++ b/coq/ethereum/shanghai/vm/gas.ast @@ -0,0 +1,853 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=4800)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RETURN_DATA_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_FAST_STEP', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLAKE2_PER_ROUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COLD_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2100)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_WARM_ACCESS', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=100)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_INIT_CODE_WORD_COST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_left', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='memory_cost', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='extra_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='call_stipend', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Expr( + value=Constant(value='\n Calculates the MessageCallGas (cost and stipend) for\n executing call Opcodes.\n\n Parameters\n ----------\n value:\n The amount of `ETH` that needs to be transferred.\n gas :\n The amount of gas provided to the message-call.\n gas_left :\n The amount of gas left in the current frame.\n memory_cost :\n The amount needed to extend the memory in the current frame.\n extra_gas :\n The amount of gas needed for transferring value + creating a new\n account inside a message call.\n call_stipend :\n The amount of stipend provided to a message call to execute code while\n transferring value(ETH).\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='call_stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='call_stipend', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='extra_gas', ctx=Load()), + op=Add(), + right=Name(id='memory_cost', ctx=Load()))]), + body=[ + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='gas', ctx=Load()), + Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='gas_left', ctx=Load()), + op=Sub(), + right=Name(id='memory_cost', ctx=Load())), + op=Sub(), + right=Name(id='extra_gas', ctx=Load()))], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load())), + FunctionDef( + name='max_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the maximum gas that is allowed for making a message call\n\n Parameters\n ----------\n gas :\n The amount of gas provided to the message-call.\n\n Returns\n -------\n max_allowed_message_call_gas: `ethereum.base_types.Uint`\n The maximum gas allowed for making the message-call.\n ')), + Return( + value=BinOp( + left=Name(id='gas', ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='gas', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]))))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='init_code_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='init_code_length', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas to be charged for the init code in CREAT*\n opcodes as well as create transactions.\n\n Parameters\n ----------\n init_code_length :\n The length of the init code provided to the opcode\n or a create transaction\n\n Returns\n -------\n init_code_gas: `ethereum.base_types.Uint`\n The gas to be charged for the init code.\n ')), + Return( + value=BinOp( + left=BinOp( + left=Name(id='GAS_INIT_CODE_WORD_COST', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='init_code_length', ctx=Load())], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/gas.v b/coq/ethereum/shanghai/vm/gas.v new file mode 100644 index 0000000000..de3d208eed --- /dev/null +++ b/coq/ethereum/shanghai/vm/gas.v @@ -0,0 +1,190 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (value : U256) (gas : Uint) (gas_left : Uint) (memory_cost : Uint) (extra_gas : Uint) (call_stipend : Uint) : M MessageCallGas := + (* + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "gas" [[ + M.get_local ~(| "min" |) ~(| + gas, + M.get_local ~(| "max_message_call_gas" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition max_message_call_gas (gas : Uint) : M Uint := + (* + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + *) + (* TODO statement *) + M.pure tt. + +Definition init_code_cost (init_code_length : Uint) : M Uint := + (* + Calculates the gas to be charged for the init code in CREAT* + opcodes as well as create transactions. + + Parameters + ---------- + init_code_length : + The length of the init code provided to the opcode + or a create transaction + + Returns + ------- + init_code_gas: `ethereum.base_types.Uint` + The gas to be charged for the init code. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/instructions/__init__.ast b/coq/ethereum/shanghai/vm/instructions/__init__.ast new file mode 100644 index 0000000000..00ff5ac00f --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/__init__.ast @@ -0,0 +1,1804 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='SHL', ctx=Store())], + value=Constant(value=27)), + Assign( + targets=[ + Name(id='SHR', ctx=Store())], + value=Constant(value=28)), + Assign( + targets=[ + Name(id='SAR', ctx=Store())], + value=Constant(value=29)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='RETURNDATASIZE', ctx=Store())], + value=Constant(value=61)), + Assign( + targets=[ + Name(id='RETURNDATACOPY', ctx=Store())], + value=Constant(value=62)), + Assign( + targets=[ + Name(id='EXTCODEHASH', ctx=Store())], + value=Constant(value=63)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='PREVRANDAO', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='CHAINID', ctx=Store())], + value=Constant(value=70)), + Assign( + targets=[ + Name(id='SELFBALANCE', ctx=Store())], + value=Constant(value=71)), + Assign( + targets=[ + Name(id='BASEFEE', ctx=Store())], + value=Constant(value=72)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH0', ctx=Store())], + value=Constant(value=95)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='CREATE2', ctx=Store())], + value=Constant(value=245)), + Assign( + targets=[ + Name(id='STATICCALL', ctx=Store())], + value=Constant(value=250)), + Assign( + targets=[ + Name(id='REVERT', ctx=Store())], + value=Constant(value=253)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SHR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SAR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PREVRANDAO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CHAINID', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURNDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODEHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFBALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BASEFEE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STATICCALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='REVERT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE2', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shl', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_shr', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_sar', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='prev_randao', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='returndatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodehash', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='self_balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='base_fee', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push0', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='staticcall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='revert', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create2', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/instructions/__init__.v b/coq/ethereum/shanghai/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/shanghai/vm/instructions/arithmetic.ast b/coq/ethereum/shanghai/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/instructions/arithmetic.v b/coq/ethereum/shanghai/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..bf74628847 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/instructions/bitwise.ast b/coq/ethereum/shanghai/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..b72397f0ec --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/bitwise.ast @@ -0,0 +1,751 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shl', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift left (SHL) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='value', ctx=Load()), + op=LShift(), + right=Name(id='shift', ctx=Load())), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]))], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_shr', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Logical shift right (SHR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_sar', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Arithmetic shift right (SAR) operation of the top 2 elements of the stack.\n Pushes the result back on the stack.\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='shift', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='signed_value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='shift', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=256)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + BinOp( + left=Name(id='signed_value', ctx=Load()), + op=RShift(), + right=Name(id='shift', ctx=Load()))], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='signed_value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load()))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/instructions/bitwise.v b/coq/ethereum/shanghai/vm/instructions/bitwise.v new file mode 100644 index 0000000000..d2e1b28c76 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/bitwise.v @@ -0,0 +1,309 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shl (evm : Evm) : M unit := + (* + Logical shift left (SHL) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_shr (evm : Evm) : M unit := + (* + Logical shift right (SHR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_sar (evm : Evm) : M unit := + (* + Arithmetic shift right (SAR) operation of the top 2 elements of the stack. + Pushes the result back on the stack. + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "shift" [[ + M.get_local ~(| "int" |) ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "signed_value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/instructions/block.ast b/coq/ethereum/shanghai/vm/instructions/block.ast new file mode 100644 index 0000000000..fb05a0d612 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/block.ast @@ -0,0 +1,495 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.shanghai.vm.exceptions.StackUnderflowError`\n If `len(stack)` is less than `1`.\n :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `20`.\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='prev_randao', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the `prev_randao` value onto the stack.\n\n The `prev_randao` value is the random output of the beacon chain's\n randomness oracle for the previous block.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='prev_randao', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='chain_id', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the chain id onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n Raises\n ------\n :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError`\n If `len(stack)` is equal to `1024`.\n :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError`\n If `evm.gas_left` is less than `2`.\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/instructions/block.v b/coq/ethereum/shanghai/vm/instructions/block.v new file mode 100644 index 0000000000..c843334534 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/block.v @@ -0,0 +1,283 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.shanghai.vm.exceptions.StackUnderflowError` + If `len(stack)` is less than `1`. + :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `20`. + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition prev_randao (evm : Evm) : M unit := + (* + Push the `prev_randao` value onto the stack. + + The `prev_randao` value is the random output of the beacon chain's + randomness oracle for the previous block. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "prev_randao" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition chain_id (evm : Evm) : M unit := + (* + Push the chain id onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + Raises + ------ + :py:class:`~ethereum.shanghai.vm.exceptions.StackOverflowError` + If `len(stack)` is equal to `1024`. + :py:class:`~ethereum.shanghai.vm.exceptions.OutOfGasError` + If `evm.gas_left` is less than `2`. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "chain_id" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/instructions/comparison.ast b/coq/ethereum/shanghai/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/instructions/comparison.v b/coq/ethereum/shanghai/vm/instructions/comparison.v new file mode 100644 index 0000000000..c0e9153fec --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/instructions/control_flow.ast b/coq/ethereum/shanghai/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/instructions/control_flow.v b/coq/ethereum/shanghai/vm/instructions/control_flow.v new file mode 100644 index 0000000000..a6aab3d2bd --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.exceptions. +Require ethereum.shanghai.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/instructions/environment.ast b/coq/ethereum/shanghai/vm/instructions/environment.ast new file mode 100644 index 0000000000..60bbfdaff1 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/environment.ast @@ -0,0 +1,1828 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfBoundsRead')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_COLD_ACCOUNT_ACCESS'), + alias(name='GAS_COPY'), + alias(name='GAS_FAST_STEP'), + alias(name='GAS_RETURN_DATA_COPY'), + alias(name='GAS_VERY_LOW'), + alias(name='GAS_WARM_ACCESS'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_WARM_ACCESS', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the size of the return data buffer onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='returndatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copies data from the return data buffer code to memory\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='return_data_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_RETURN_DATA_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='return_data_start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfBoundsRead', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load()), + slice=Slice( + lower=Name(id='return_data_start_position', ctx=Load()), + upper=BinOp( + left=Name(id='return_data_start_position', ctx=Load()), + op=Add(), + right=Name(id='size', ctx=Load()))), + ctx=Load())), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodehash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns the keccak256 hash of a contract’s bytecode\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='EMPTY_ACCOUNT', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='codehash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codehash', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='self_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the current address to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_FAST_STEP', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='base_fee', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the base fee of the current block on to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/instructions/environment.v b/coq/ethereum/shanghai/vm/instructions/environment.v new file mode 100644 index 0000000000..2edf834c61 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/environment.v @@ -0,0 +1,728 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.shanghai.fork_types. +Require ethereum.shanghai.state. +Require ethereum.shanghai.utils.address. +Require ethereum.shanghai.vm.memory. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.exceptions. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatasize (evm : Evm) : M unit := + (* + Pushes the size of the return data buffer onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "return_data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition returndatacopy (evm : Evm) : M unit := + (* + Copies data from the return data buffer code to memory + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "return_data_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + (* TODO expression *) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodehash (evm : Evm) : M unit := + (* + Returns the keccak256 hash of a contract’s bytecode + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "account" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codehash" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition self_balance (evm : Evm) : M unit := + (* + Pushes the balance of the current address to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_FAST_STEP + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition base_fee (evm : Evm) : M unit := + (* + Pushes the base fee of the current block on to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "base_fee_per_gas" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/instructions/keccak.ast b/coq/ethereum/shanghai/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/instructions/keccak.v b/coq/ethereum/shanghai/vm/instructions/keccak.v new file mode 100644 index 0000000000..fa3a063222 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.memory. +Require ethereum.shanghai.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/instructions/log.ast b/coq/ethereum/shanghai/vm/instructions/log.ast new file mode 100644 index 0000000000..0ded0e04ba --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/log.ast @@ -0,0 +1,323 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/instructions/log.v b/coq/ethereum/shanghai/vm/instructions/log.v new file mode 100644 index 0000000000..a66b3318e5 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/log.v @@ -0,0 +1,79 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.shanghai.blocks. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.exceptions. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.memory. +Require ethereum.shanghai.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO statement *) + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/instructions/memory.ast b/coq/ethereum/shanghai/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/instructions/memory.v b/coq/ethereum/shanghai/vm/instructions/memory.v new file mode 100644 index 0000000000..2ae905686e --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.memory. +Require ethereum.shanghai.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/instructions/stack.ast b/coq/ethereum/shanghai/vm/instructions/stack.ast new file mode 100644 index 0000000000..79c3c451b2 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/stack.ast @@ -0,0 +1,1110 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack. Push zero if num_bytes is zero.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack. Push zero if num_bytes is zero.\n\n ')), + Pass(), + If( + test=Compare( + left=Name(id='num_bytes', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/instructions/stack.v b/coq/ethereum/shanghai/vm/instructions/stack.v new file mode 100644 index 0000000000..ed16cd5863 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/stack.v @@ -0,0 +1,150 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.exceptions. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. Push zero if num_bytes is zero. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. Push zero if num_bytes is zero. + + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/instructions/storage.ast b/coq/ethereum/shanghai/vm/instructions/storage.ast new file mode 100644 index 0000000000..68640a90a8 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/storage.ast @@ -0,0 +1,551 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='get_storage_original'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_STIPEND'), + alias(name='GAS_COLD_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='GAS_WARM_ACCESS'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_WARM_ACCESS', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_COLD_SLOAD', ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='original_value', ctx=Store())], + value=Call( + func=Name(id='get_storage_original', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + If( + test=Compare( + left=Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_COLD_SLOAD', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='current_value', ctx=Load())]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())])]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_COLD_SLOAD', ctx=Load())))])], + orelse=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))]), + If( + test=Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='new_value', ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='original_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='GAS_STORAGE_SET', ctx=Load()), + op=Sub(), + right=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + keywords=[]))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='GAS_STORAGE_UPDATE', ctx=Load()), + op=Sub(), + right=Name(id='GAS_COLD_SLOAD', ctx=Load())), + op=Sub(), + right=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + keywords=[]))])], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/instructions/storage.v b/coq/ethereum/shanghai/vm/instructions/storage.v new file mode 100644 index 0000000000..b17f648ba0 --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/storage.v @@ -0,0 +1,121 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.shanghai.state. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.exceptions. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "original_value" [[ + state.get_storage_original ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* M.assign "gas_cost" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/instructions/system.ast b/coq/ethereum/shanghai/vm/instructions/system.ast new file mode 100644 index 0000000000..f77748544c --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/system.ast @@ -0,0 +1,2953 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='is_account_alive'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='compute_create2_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError'), + alias(name='Revert'), + alias(name='WriteInStaticContext')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL_VALUE'), + alias(name='GAS_COLD_ACCOUNT_ACCESS'), + alias(name='GAS_CREATE'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='GAS_NEW_ACCOUNT'), + alias(name='GAS_SELF_DESTRUCT'), + alias(name='GAS_SELF_DESTRUCT_NEW_ACCOUNT'), + alias(name='GAS_WARM_ACCESS'), + alias(name='GAS_ZERO'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas'), + alias(name='init_code_cost'), + alias(name='max_message_call_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='generic_create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='endowment', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='contract_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='memory_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='init_code_gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Core logic used by the `CREATE*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='MAX_CODE_SIZE'), + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='call_data', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='MAX_CODE_SIZE', ctx=Load()))]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='contract_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='create_message_gas', ctx=Load())), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='is_static', + value=Constant(value=False)), + keyword( + arg='accessed_addresses', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='init_code_gas', ctx=Store())], + value=Call( + func=Name(id='init_code_cost', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())), + op=Add(), + right=Name(id='init_code_gas', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load()), + Name(id='init_code_gas', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create2', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Creates a new account with associated code.\n\n It's similar to CREATE opcode except that the address of new account\n depends on the init_code instead of the nonce of sender.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ")), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='salt', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='call_data_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='init_code_gas', ctx=Store())], + value=Call( + func=Name(id='init_code_cost', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='call_data_words', ctx=Load()))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())), + op=Add(), + right=Name(id='init_code_gas', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_create2_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='salt', ctx=Load()), + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='generic_create', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='endowment', ctx=Load()), + Name(id='contract_address', ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load()), + Name(id='init_code_gas', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='is_staticcall', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='is_static', + value=IfExp( + test=Name(id='is_staticcall', ctx=Load()), + body=Constant(value=True), + orelse=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()))), + keyword( + arg='accessed_addresses', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()), + attr='copy', + ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='to', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=BoolOp( + op=Or(), + values=[ + Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[]), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='access_gas_cost', ctx=Load()), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='code_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=Name(id='access_gas_cost', ctx=Load()), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Store())], + value=Constant(value=b'')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SELF_DESTRUCT', ctx=Load())), + If( + test=Compare( + left=Name(id='beneficiary', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[])), + Compare( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='is_static', + ctx=Load()), + body=[ + Raise( + exc=Name(id='WriteInStaticContext', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='code_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='access_gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='staticcall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='to', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_WARM_ACCESS', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accessed_addresses', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='access_gas_cost', ctx=Store())], + value=Name(id='GAS_COLD_ACCOUNT_ACCESS', ctx=Load()))]), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='access_gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='revert', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop execution and revert state changes, without consuming all provided gas\n and also has the ability to return a reason\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Name(id='output', ctx=Load())], + keywords=[])), + Raise( + exc=Name(id='Revert', ctx=Load())), + Pass()], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/instructions/system.v b/coq/ethereum/shanghai/vm/instructions/system.v new file mode 100644 index 0000000000..244e30b62a --- /dev/null +++ b/coq/ethereum/shanghai/vm/instructions/system.v @@ -0,0 +1,796 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.shanghai.fork_types. +Require ethereum.shanghai.state. +Require ethereum.shanghai.utils.address. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.exceptions. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.memory. +Require ethereum.shanghai.vm.stack. + +Definition generic_create (evm : Evm) (endowment : U256) (contract_address : Address) (memory_start_position : U256) (memory_size : U256) (init_code_gas : Uint) : M unit := + (* + Core logic used by the `CREATE*` family of opcodes. + *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_start_position, + memory_size + |) in + ]] in + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| evm, "accessed_addresses" |), "add" |) ~(| + contract_address + |) ]] in + do* M.assign "create_message_gas" [[ + gas.max_message_call_gas ~(| + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) in + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_local ~(| "create_message_gas" |) + ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ state.increment_nonce ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_create_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "init_code_gas" [[ + gas.init_code_cost ~(| + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "memory_size" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |), + M.get_local ~(| "init_code_gas" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition create2 (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + It's similar to CREATE opcode except that the address of new account + depends on the init_code instead of the nonce of sender. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "salt" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "call_data_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "init_code_gas" [[ + gas.init_code_cost ~(| + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "memory_size" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_create2_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "salt" |), + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |) + |) + |) in + ]] in + do* [[ M.get_local ~(| "generic_create" |) ~(| + evm, + M.get_local ~(| "endowment" |), + M.get_local ~(| "contract_address" |), + M.get_local ~(| "memory_start_position" |), + M.get_local ~(| "memory_size" |), + M.get_local ~(| "init_code_gas" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (is_staticcall : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_SELF_DESTRUCT in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + (* TODO statement *) + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + M.get_local ~(| "access_gas_cost" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition staticcall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + M.get_local ~(| "access_gas_cost" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "to" |), + M.get_local ~(| "to" |), + True, + True, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition revert (evm : Evm) : M unit := + (* + Stop execution and revert state changes, without consuming all provided gas + and also has the ability to return a reason + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "output" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/interpreter.ast b/coq/ethereum/shanghai/vm/interpreter.ast new file mode 100644 index 0000000000..74dbe98ae4 --- /dev/null +++ b/coq/ethereum/shanghai/vm/interpreter.ast @@ -0,0 +1,1188 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Iterable'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='increment_nonce'), + alias(name='mark_account_created'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidContractPrefix'), + alias(name='InvalidOpcode'), + alias(name='OutOfGasError'), + alias(name='Revert'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_CODE_SIZE', ctx=Store())], + value=Constant(value=24576)), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `touched_accounts`: Accounts that have been touched.\n 6. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple(elts=[], ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='touched_accounts', + value=Name(id='touched_accounts', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.shanghai.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='mark_account_created', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='contract_code', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=239)]), + body=[ + Raise( + exc=Name(id='InvalidContractPrefix', ctx=Load()))], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_CODE_SIZE', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.shanghai.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='touched_accounts', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='return_data', + value=Constant(value=b'')), + keyword( + arg='error', + value=Constant(value=None)), + keyword( + arg='accessed_addresses', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='accessed_addresses', + ctx=Load())), + keyword( + arg='accessed_storage_keys', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='accessed_storage_keys', + ctx=Load()))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Constant(value=b'')), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))]), + ExceptHandler( + type=Name(id='Revert', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/interpreter.v b/coq/ethereum/shanghai/vm/interpreter.v new file mode 100644 index 0000000000..86974f46b4 --- /dev/null +++ b/coq/ethereum/shanghai/vm/interpreter.v @@ -0,0 +1,173 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.shanghai.blocks. +Require ethereum.shanghai.fork_types. +Require ethereum.shanghai.state. +Require ethereum.shanghai.vm. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.precompiled_contracts.mapping. +Require ethereum.shanghai.vm.__init__. +Require ethereum.shanghai.vm.exceptions. +Require ethereum.shanghai.vm.instructions. +Require ethereum.shanghai.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.shanghai.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.mark_account_created ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.shanghai.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/memory.ast b/coq/ethereum/shanghai/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/shanghai/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/memory.v b/coq/ethereum/shanghai/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/shanghai/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/__init__.ast b/coq/ethereum/shanghai/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..bb9991907f --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS'), + Constant(value='MODEXP_ADDRESS'), + Constant(value='ALT_BN128_ADD_ADDRESS'), + Constant(value='ALT_BN128_MUL_ADDRESS'), + Constant(value='ALT_BN128_PAIRING_CHECK_ADDRESS'), + Constant(value='BLAKE2F_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[])), + Assign( + targets=[ + Name(id='MODEXP_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x05')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x06')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x07')], + keywords=[])), + Assign( + targets=[ + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x08')], + keywords=[])), + Assign( + targets=[ + Name(id='BLAKE2F_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x09')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/__init__.v b/coq/ethereum/shanghai/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..ad37fcb596 --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.shanghai.utils.hexadecimal. diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.ast b/coq/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.ast new file mode 100644 index 0000000000..f6f077419c --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.ast @@ -0,0 +1,913 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ALT_BN128 CONTRACTS\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ALT_BN128 precompiled contracts.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.alt_bn128', + names=[ + alias(name='ALT_BN128_CURVE_ORDER'), + alias(name='ALT_BN128_PRIME'), + alias(name='BNF'), + alias(name='BNF2'), + alias(name='BNF12'), + alias(name='BNP'), + alias(name='BNP2'), + alias(name='pairing')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=2), + FunctionDef( + name='alt_bn128_add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 addition precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=150)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y1_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y1_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load()), + Name(id='x1_value', ctx=Load()), + Name(id='y1_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='p1', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x1_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y1_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=BinOp( + left=Name(id='p0', ctx=Load()), + op=Add(), + right=Name(id='p1', ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 multiplication precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6000)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='x0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='x0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y0_value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='y0_bytes', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='n', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Tuple( + elts=[ + Name(id='x0_value', ctx=Load()), + Name(id='y0_value', ctx=Load())], + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p0', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='x0_value', ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Name(id='y0_value', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='p0', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='n', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='x', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='p', ctx=Load()), + attr='y', + ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='alt_bn128_pairing_check', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The ALT_BN128 pairing check precompiled contract.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=34000), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))), + op=Add(), + right=Constant(value=45000))], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=192)), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=192))], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='values', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='j', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=Name(id='j', ctx=Load()))), + upper=BinOp( + left=BinOp( + left=Name(id='i', ctx=Load()), + op=Mult(), + right=Constant(value=192)), + op=Add(), + right=BinOp( + left=Constant(value=32), + op=Mult(), + right=BinOp( + left=Name(id='j', ctx=Load()), + op=Add(), + right=Constant(value=1))))), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='ALT_BN128_PRIME', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='values', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='p', ctx=Store())], + value=Call( + func=Name(id='BNP', ctx=Load()), + args=[ + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF', ctx=Load()), + args=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='q', ctx=Store())], + value=Call( + func=Name(id='BNP2', ctx=Load()), + args=[ + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=3), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=2), + ctx=Load())], + ctx=Load())], + keywords=[]), + Call( + func=Name(id='BNF2', ctx=Load()), + args=[ + Tuple( + elts=[ + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=5), + ctx=Load()), + Subscript( + value=Name(id='values', ctx=Load()), + slice=Constant(value=4), + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='OutOfGasError', ctx=Load()), + args=[], + keywords=[]))])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='p', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='q', ctx=Load()), + attr='mul_by', + ctx=Load()), + args=[ + Name(id='ALT_BN128_CURVE_ORDER', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='p', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])]), + Compare( + left=Name(id='q', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNP2', ctx=Load()), + attr='point_at_infinity', + ctx=Load()), + args=[], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=BinOp( + left=Name(id='result', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='pairing', ctx=Load()), + args=[ + Name(id='q', ctx=Load()), + Name(id='p', ctx=Load())], + keywords=[])))], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='result', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Attribute( + value=Name(id='BNF12', ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.v b/coq/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.v new file mode 100644 index 0000000000..8006b0bef2 --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/alt_bn128.v @@ -0,0 +1,226 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ALT_BN128 CONTRACTS +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ALT_BN128 precompiled contracts. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.alt_bn128. +Require ethereum.shanghai.vm. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.memory. +Require ethereum.shanghai.vm.exceptions. + +Definition alt_bn128_add (evm : Evm) : M unit := + (* + The ALT_BN128 addition precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 150 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "x1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x1_bytes" |) + |) + |) in + ]] in + do* M.assign "y1_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y1_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y1_bytes" |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + (* TODO expression *) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_mul (evm : Evm) : M unit := + (* + The ALT_BN128 multiplication precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + 6000 + |) + |) ]] in + do* M.assign "x0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "x0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "x0_bytes" |) + |) + |) in + ]] in + do* M.assign "y0_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "y0_value" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "y0_bytes" |) + |) + |) in + ]] in + do* M.assign "n" [[ + M.get_local ~(| "int" |) ~(| + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* M.assign "p" [[ + M.get_field ~(| M.get_local ~(| "p0" |), "mul_by" |) ~(| + M.get_local ~(| "n" |) + |) in + ]] in + (* TODO assignment *) + M.pure tt. + +Definition alt_bn128_pairing_check (evm : Evm) : M unit := + (* + The ALT_BN128 pairing check precompiled contract. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + ethereum_types.numeric.Uint ~(| + (* TODO expression *) + |) + |) ]] in + (* TODO statement *) + do* M.assign "result" [[ + M.get_field ~(| ethereum.crypto.alt_bn128.BNF12, "from_int" |) ~(| + 1 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/blake2f.ast b/coq/ethereum/shanghai/vm/precompiled_contracts/blake2f.ast new file mode 100644 index 0000000000..03747962f0 --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/blake2f.ast @@ -0,0 +1,137 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `Blake2` precompiled contract.\n')), + ImportFrom( + module='ethereum.crypto.blake2', + names=[ + alias(name='Blake2b')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BLAKE2_PER_ROUND'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidParameter')], + level=2), + FunctionDef( + name='blake2f', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the Blake2 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Constant(value=213)]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='blake2b', ctx=Store())], + value=Call( + func=Name(id='Blake2b', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='rounds', ctx=Store()), + Name(id='h', ctx=Store()), + Name(id='m', ctx=Store()), + Name(id='t_0', ctx=Store()), + Name(id='t_1', ctx=Store()), + Name(id='f', ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='get_blake2_parameters', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_BLAKE2_PER_ROUND', ctx=Load()), + op=Mult(), + right=Name(id='rounds', ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=Name(id='f', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + List( + elts=[ + Constant(value=0), + Constant(value=1)], + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidParameter', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='blake2b', ctx=Load()), + attr='compress', + ctx=Load()), + args=[ + Name(id='rounds', ctx=Load()), + Name(id='h', ctx=Load()), + Name(id='m', ctx=Load()), + Name(id='t_0', ctx=Load()), + Name(id='t_1', ctx=Load()), + Name(id='f', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/blake2f.v b/coq/ethereum/shanghai/vm/precompiled_contracts/blake2f.v new file mode 100644 index 0000000000..9c740d7e14 --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/blake2f.v @@ -0,0 +1,46 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Blake2 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `Blake2` precompiled contract. +*) + +Require ethereum.crypto.blake2. +Require ethereum.shanghai.vm. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.exceptions. + +Definition blake2f (evm : Evm) : M unit := + (* + Writes the Blake2 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + (* TODO statement *) + do* M.assign "blake2b" [[ + ethereum.crypto.blake2.Blake2b ~(| + + |) in + ]] in + (* TODO assignment *) + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/shanghai/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/shanghai/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..e3e0b8b06b --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.shanghai.vm. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/identity.ast b/coq/ethereum/shanghai/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/identity.v b/coq/ethereum/shanghai/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..0d2aceb57a --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.shanghai.vm. +Require ethereum.shanghai.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/mapping.ast b/coq/ethereum/shanghai/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..cec40e5736 --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,97 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ALT_BN128_ADD_ADDRESS'), + alias(name='ALT_BN128_MUL_ADDRESS'), + alias(name='ALT_BN128_PAIRING_CHECK_ADDRESS'), + alias(name='BLAKE2F_ADDRESS'), + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='MODEXP_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='alt_bn128', + names=[ + alias(name='alt_bn128_add'), + alias(name='alt_bn128_mul'), + alias(name='alt_bn128_pairing_check')], + level=1), + ImportFrom( + module='blake2f', + names=[ + alias(name='blake2f')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='modexp', + names=[ + alias(name='modexp')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load()), + Name(id='MODEXP_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_ADD_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_MUL_ADDRESS', ctx=Load()), + Name(id='ALT_BN128_PAIRING_CHECK_ADDRESS', ctx=Load()), + Name(id='BLAKE2F_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load()), + Name(id='modexp', ctx=Load()), + Name(id='alt_bn128_add', ctx=Load()), + Name(id='alt_bn128_mul', ctx=Load()), + Name(id='alt_bn128_pairing_check', ctx=Load()), + Name(id='blake2f', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/mapping.v b/coq/ethereum/shanghai/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..2297fadb16 --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/mapping.v @@ -0,0 +1,25 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.shanghai.fork_types. +Require ethereum.shanghai.vm.precompiled_contracts.__init__. +Require ethereum.shanghai.vm.precompiled_contracts.alt_bn128. +Require ethereum.shanghai.vm.precompiled_contracts.blake2f. +Require ethereum.shanghai.vm.precompiled_contracts.ecrecover. +Require ethereum.shanghai.vm.precompiled_contracts.identity. +Require ethereum.shanghai.vm.precompiled_contracts.modexp. +Require ethereum.shanghai.vm.precompiled_contracts.ripemd160. +Require ethereum.shanghai.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/modexp.ast b/coq/ethereum/shanghai/vm/precompiled_contracts/modexp.ast new file mode 100644 index 0000000000..42ecfa223f --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/modexp.ast @@ -0,0 +1,638 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `MODEXP` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='charge_gas')], + level=3), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + Assign( + targets=[ + Name(id='GQUADDIVISOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + FunctionDef( + name='modexp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and.\n `modulus`. The return value is the same length as the modulus.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='base_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_length', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp_start', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + op=Add(), + right=Name(id='base_length', ctx=Load()))), + Assign( + targets=[ + Name(id='exp_head', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Call( + func=Name(id='min', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='gas_cost', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load()), + Name(id='exp_length', ctx=Load()), + Name(id='exp_head', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='base_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='modulus_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Name(id='base_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exp', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='exp_start', ctx=Load()), + Name(id='exp_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='modulus_start', ctx=Store())], + value=BinOp( + left=Name(id='exp_start', ctx=Load()), + op=Add(), + right=Name(id='exp_length', ctx=Load()))), + Assign( + targets=[ + Name(id='modulus', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='modulus_start', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='modulus', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'\x00')], + keywords=[]), + op=Mult(), + right=Name(id='modulus_length', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exp', ctx=Load()), + Name(id='modulus', ctx=Load())], + keywords=[]), + attr='to_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[]), + Constant(value='big')], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='complexity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Estimate the complexity of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n Returns\n -------\n\n complexity : `Uint`\n Complexity of performing the operation.\n ')), + Assign( + targets=[ + Name(id='max_length', ctx=Store())], + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load())], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='modulus_length', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='max_length', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Return( + value=BinOp( + left=Name(id='words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='iterations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the number of iterations required to perform a modular\n exponentiation.\n\n Parameters\n ----------\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n iterations : `Uint`\n Number of iterations.\n ')), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + Compare( + left=Name(id='exponent_head', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])])]), + body=[ + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Name(id='exponent_length', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='bit_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='bit_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='bit_length', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Name(id='bit_length', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='length_part', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])))), + Assign( + targets=[ + Name(id='bits_part', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='exponent_head', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='bits_part', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='bits_part', ctx=Store()), + op=Sub(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=BinOp( + left=Name(id='length_part', ctx=Load()), + op=Add(), + right=Name(id='bits_part', ctx=Load())))])]), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='count', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='base_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='modulus_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_length', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='exponent_head', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the gas cost of performing a modular exponentiation.\n\n Parameters\n ----------\n\n base_length :\n Length of the array representing the base integer.\n\n modulus_length :\n Length of the array representing the modulus integer.\n\n exponent_length :\n Length of the array representing the exponent integer.\n\n exponent_head :\n First 32 bytes of the exponent (with leading zero padding if it is\n shorter than 32 bytes), as an unsigned integer.\n\n Returns\n -------\n\n gas_cost : `Uint`\n Gas required for performing the operation.\n ')), + Assign( + targets=[ + Name(id='multiplication_complexity', ctx=Store())], + value=Call( + func=Name(id='complexity', ctx=Load()), + args=[ + Name(id='base_length', ctx=Load()), + Name(id='modulus_length', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='iteration_count', ctx=Store())], + value=Call( + func=Name(id='iterations', ctx=Load()), + args=[ + Name(id='exponent_length', ctx=Load()), + Name(id='exponent_head', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cost', ctx=Store())], + value=BinOp( + left=Name(id='multiplication_complexity', ctx=Load()), + op=Mult(), + right=Name(id='iteration_count', ctx=Load()))), + AugAssign( + target=Name(id='cost', ctx=Store()), + op=FloorDiv(), + value=Name(id='GQUADDIVISOR', ctx=Load())), + Return( + value=Call( + func=Name(id='max', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[]), + Name(id='cost', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/modexp.v b/coq/ethereum/shanghai/vm/precompiled_contracts/modexp.v new file mode 100644 index 0000000000..170de5910f --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/modexp.v @@ -0,0 +1,236 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) MODEXP PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `MODEXP` precompiled contract. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.shanghai.vm. +Require ethereum.shanghai.vm.gas. +Require ethereum.shanghai.vm.memory. + +Definition modexp (evm : Evm) : M unit := + (* + Calculates `(base**exp) % modulus` for arbitrary sized `base`, `exp` and. + `modulus`. The return value is the same length as the modulus. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "base_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "modulus_length" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "exp_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "exp_head" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "min" |) ~(| + ethereum_types.numeric.U256 ~(| + 32 + |), + M.get_local ~(| "exp_length" |) + |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) ~(| + M.get_local ~(| "base_length" |), + M.get_local ~(| "modulus_length" |), + M.get_local ~(| "exp_length" |), + M.get_local ~(| "exp_head" |) + |) + |) ]] in + (* TODO statement *) + do* M.assign "base" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + M.get_local ~(| "base_length" |) + |) + |) in + ]] in + do* M.assign "exp" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "exp_start" |), + M.get_local ~(| "exp_length" |) + |) + |) in + ]] in + do* M.assign "modulus_start" [[ + (* TODO expression *) in + ]] in + do* M.assign "modulus" [[ + M.get_field ~(| ethereum_types.numeric.Uint, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_local ~(| "data" |), + M.get_local ~(| "modulus_start" |), + M.get_local ~(| "modulus_length" |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition complexity (base_length : U256) (modulus_length : U256) : M Uint := + (* + Estimate the complexity of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + Returns + ------- + + complexity : `Uint` + Complexity of performing the operation. + *) + do* M.assign "max_length" [[ + M.get_local ~(| "max" |) ~(| + ethereum_types.numeric.Uint ~(| + base_length + |), + ethereum_types.numeric.Uint ~(| + modulus_length + |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition iterations (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the number of iterations required to perform a modular + exponentiation. + + Parameters + ---------- + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + iterations : `Uint` + Number of iterations. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition gas_cost (base_length : U256) (modulus_length : U256) (exponent_length : U256) (exponent_head : Uint) : M Uint := + (* + Calculate the gas cost of performing a modular exponentiation. + + Parameters + ---------- + + base_length : + Length of the array representing the base integer. + + modulus_length : + Length of the array representing the modulus integer. + + exponent_length : + Length of the array representing the exponent integer. + + exponent_head : + First 32 bytes of the exponent (with leading zero padding if it is + shorter than 32 bytes), as an unsigned integer. + + Returns + ------- + + gas_cost : `Uint` + Gas required for performing the operation. + *) + do* M.assign "multiplication_complexity" [[ + M.get_local ~(| "complexity" |) ~(| + base_length, + modulus_length + |) in + ]] in + do* M.assign "iteration_count" [[ + M.get_local ~(| "iterations" |) ~(| + exponent_length, + exponent_head + |) in + ]] in + do* M.assign "cost" [[ + (* TODO expression *) in + ]] in + do* M.aug_assign [[ M.get_local ~(| "cost" |) ]] [[ + M.get_local ~(| "GQUADDIVISOR" |) + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/shanghai/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/shanghai/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/sha256.ast b/coq/ethereum/shanghai/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/precompiled_contracts/sha256.v b/coq/ethereum/shanghai/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/shanghai/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/runtime.ast b/coq/ethereum/shanghai/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/shanghai/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/runtime.v b/coq/ethereum/shanghai/vm/runtime.v new file mode 100644 index 0000000000..b72b5a6c10 --- /dev/null +++ b/coq/ethereum/shanghai/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.shanghai.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/shanghai/vm/stack.ast b/coq/ethereum/shanghai/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/shanghai/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/shanghai/vm/stack.v b/coq/ethereum/shanghai/vm/stack.v new file mode 100644 index 0000000000..017290a34f --- /dev/null +++ b/coq/ethereum/shanghai/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.shanghai.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/__init__.ast b/coq/ethereum/spurious_dragon/__init__.ast new file mode 100644 index 0000000000..b974d9a9dd --- /dev/null +++ b/coq/ethereum/spurious_dragon/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe Spurious Dragon fork is the second of two forks responding to a\ndenial-of-service attack on the Ethereum network. It tunes the prices of EVM\ninstructions, adds protection against replaying transaction on different\nchains, limits the maximum size of contract code, and enables the removal of\nempty accounts.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=2675000)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/__init__.v b/coq/ethereum/spurious_dragon/__init__.v new file mode 100644 index 0000000000..32cf1d8dc8 --- /dev/null +++ b/coq/ethereum/spurious_dragon/__init__.v @@ -0,0 +1,10 @@ +(* Generated *) +(* +The Spurious Dragon fork is the second of two forks responding to a +denial-of-service attack on the Ethereum network. It tunes the prices of EVM +instructions, adds protection against replaying transaction on different +chains, limits the maximum size of contract code, and enables the removal of +empty accounts. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/spurious_dragon/blocks.ast b/coq/ethereum/spurious_dragon/blocks.ast new file mode 100644 index 0000000000..dce2db5da0 --- /dev/null +++ b/coq/ethereum/spurious_dragon/blocks.ast @@ -0,0 +1,218 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mix_digest', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='post_state', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/blocks.v b/coq/ethereum/spurious_dragon/blocks.v new file mode 100644 index 0000000000..9297a17de6 --- /dev/null +++ b/coq/ethereum/spurious_dragon/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.spurious_dragon.fork_types. +Require ethereum.spurious_dragon.transactions. diff --git a/coq/ethereum/spurious_dragon/bloom.ast b/coq/ethereum/spurious_dragon/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/spurious_dragon/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/bloom.v b/coq/ethereum/spurious_dragon/bloom.v new file mode 100644 index 0000000000..29165c028c --- /dev/null +++ b/coq/ethereum/spurious_dragon/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.spurious_dragon.blocks. +Require ethereum.spurious_dragon.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/fork.ast b/coq/ethereum/spurious_dragon/fork.ast new file mode 100644 index 0000000000..3febeaa2f1 --- /dev/null +++ b/coq/ethereum/spurious_dragon/fork.ast @@ -0,0 +1,3133 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.ethash', + names=[ + alias(name='dataset_size'), + alias(name='generate_cache'), + alias(name='hashimoto_light')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty'), + alias(name='create_ether'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='Transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BLOCK_REWARD', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=5), + op=Mult(), + right=BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=18)))], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=131072)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_OMMER_DEPTH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='validate_ommers', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='chain', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='chain', ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_difficulty', ctx=Store())], + value=Call( + func=Name(id='calculate_block_difficulty', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_difficulty', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='validate_proof_of_work', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generate_header_hash_for_pow', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate rlp hash of the header which is to be used for Proof-of-Work\n verification.\n\n In other words, the PoW artefacts `mix_digest` and `nonce` are ignored\n while calculating this hash.\n\n A particular PoW is valid for a single hash, that hash is computed by\n this function. The `nonce` and `mix_digest` are omitted from this hash\n because they are being changed by miners in their search for a sufficient\n proof-of-work.\n\n Parameters\n ----------\n header :\n The header object for which the hash is to be generated.\n\n Returns\n -------\n hash : `Hash32`\n The PoW valid rlp hash of the passed in header.\n ')), + Assign( + targets=[ + Name(id='header_data_without_pow_artefacts', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='state_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='transactions_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='receipt_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='bloom', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='header_data_without_pow_artefacts', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='validate_proof_of_work', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the Proof of Work constraints.\n\n In order to verify that a miner's proof-of-work is valid for a block, a\n ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``\n hash function. The mix digest is a hash of the header and the nonce that\n is passed through and it confirms whether or not proof-of-work was done\n on the correct block. The result is the actual hash value of the block.\n\n Parameters\n ----------\n header :\n Header of interest.\n ")), + Assign( + targets=[ + Name(id='header_hash', ctx=Store())], + value=Call( + func=Name(id='generate_header_hash_for_pow', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache', ctx=Store())], + value=Call( + func=Name(id='generate_cache', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='mix_digest', ctx=Store()), + Name(id='result', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='hashimoto_light', ctx=Load()), + args=[ + Name(id='header_hash', ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + Name(id='cache', ctx=Load()), + Call( + func=Name(id='dataset_size', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='mix_digest', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='mix_digest', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='limit', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='limit', ctx=Load()), + op=FloorDiv(), + right=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n gas_available :\n The gas remaining in the block.\n chain_id :\n The ID of the current chain.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + Return( + value=Name(id='sender_address', ctx=Load()))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='post_state', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n post_state :\n The state root immediately after this transaction.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='post_state', + value=Name(id='post_state', ctx=Load())), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + Return( + value=Name(id='receipt', ctx=Load()))], + decorator_list=[], + returns=Name(id='Receipt', ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='block_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n block_difficulty :\n Difficulty of the block.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='transactions', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='tx', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='gas_available', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='gas_price', + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='difficulty', + value=Name(id='block_difficulty', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[]), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='pay_rewards', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='block_number', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='ommers', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='validate_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='block_header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the ommers mentioned in the block.\n\n An ommer block is a block that wasn't canonically added to the\n blockchain because it wasn't validated as fast as the canonical block\n but was mined at the same time.\n\n To be considered valid, the ommers must adhere to the rules defined in\n the Ethereum protocol. The maximum amount of ommers is 2 per block and\n there cannot be duplicate ommers in a block. Many of the other ommer\n constraints are listed in the in-line comments of this function.\n\n Parameters\n ----------\n ommers :\n List of ommers mentioned in the current block.\n block_header:\n The header of current block.\n chain :\n History and current state.\n ")), + Assign( + targets=[ + Name(id='block_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='block_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='ommers_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return()], + orelse=[]), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + op=Sub(), + right=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Name(id='ommer', ctx=Load()), + Name(id='ommer_parent_header', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=2)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommers_hashes', ctx=Store())], + value=ListComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + ifs=[], + is_async=0)])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[])], + keywords=[])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_canonical_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=BinOp( + left=Name(id='MAX_OMMER_DEPTH', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + ctx=Load())), + Assign( + targets=[ + Name(id='recent_canonical_block_hashes', ctx=Store())], + value=SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='recent_ommers_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + simple=1), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='recent_ommers_hashes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='recent_ommers_hashes', ctx=Load()), + attr='union', + ctx=Load()), + args=[ + SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='ommer_index', ctx=Store()), + Name(id='ommer', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='ommer_hash', ctx=Store())], + value=Subscript( + value=Name(id='ommers_hashes', ctx=Load()), + slice=Name(id='ommer_index', ctx=Load()), + ctx=Load())), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='block_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_ommers_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='ommer_age', ctx=Load())]), + Compare( + left=Name(id='ommer_age', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_OMMER_DEPTH', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='parent_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pay_rewards', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pay rewards to the block miner as well as the ommers miners.\n\n The miner of the canonical block is rewarded with the predetermined\n block reward, ``BLOCK_REWARD``, plus a variable award based off of the\n number of ommer blocks that were mined around the same time, and included\n in the canonical block's header. An ommer block is a block that wasn't\n added to the canonical blockchain because it wasn't validated as fast as\n the accepted block but was mined at the same time. Although not all blocks\n that are mined are added to the canonical chain, miners are still paid a\n reward for their efforts. This reward is called an ommer reward and is\n calculated based on the number associated with the ommer block that they\n mined.\n\n Parameters\n ----------\n state :\n Current account state.\n block_number :\n Position of the block within the chain.\n coinbase :\n Address of account which receives block reward and transaction fees.\n ommers :\n List of ommers mentioned in the current block.\n ")), + Assign( + targets=[ + Name(id='ommer_count', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='miner_reward', ctx=Store())], + value=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='ommer_count', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='miner_reward', ctx=Load())], + keywords=[])), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_number', ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='ommer_miner_reward', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Sub(), + right=Name(id='ommer_age', ctx=Load())), + op=Mult(), + right=Name(id='BLOCK_REWARD', ctx=Load())), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='ommer_miner_reward', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + If( + test=Compare( + left=Name(id='coinbase_balance_after_mining_fee', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]))], + orelse=[])]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Name(id='TX_CREATE_COST', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n ID of the executing chain.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='v', ctx=Store()), + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=28)])]), + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash_pre155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='chain_id_x2', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load())], + keywords=[]), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=36)], + keywords=[]), + op=Add(), + right=Name(id='chain_id_x2', ctx=Load()))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=35)], + keywords=[])), + op=Sub(), + right=Name(id='chain_id_x2', ctx=Load())), + Call( + func=Name(id='signing_hash_155', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='chain_id', ctx=Load())], + keywords=[])], + keywords=[]))]), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash_pre155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a legacy (pre EIP 155) signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='signing_hash_155', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='chain_id', + annotation=Name(id='U64', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compute the hash of a transaction used in a EIP 155 signature.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n chain_id :\n The id of the current chain.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ')), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='chain_id', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_difficulty', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes difficulty of a block using its header and parent header.\n\n The difficulty is determined by the time the block was created after its\n parent. The ``offset`` is calculated using the parent block's difficulty,\n ``parent_difficulty``, and the timestamp between blocks. This offset is\n then added to the parent difficulty and is stored as the ``difficulty``\n variable. If the time between the block and its parent is too short, the\n offset will result in a positive number thus making the sum of\n ``parent_difficulty`` and ``offset`` to be a greater value in order to\n avoid mass forking. But, if the time is long enough, then the offset\n results in a negative value making the block less difficult than\n its parent.\n\n The base standard for a block's difficulty is the predefined value\n set for the genesis block since it has no parent. So, a block\n can't be less difficult than the genesis block, therefore each block's\n difficulty is set to the maximum value between the calculated\n difficulty and the ``GENESIS_DIFFICULTY``.\n\n Parameters\n ----------\n block_number :\n Block number of the block.\n block_timestamp :\n Timestamp of the block.\n parent_timestamp :\n Timestamp of the parent block.\n parent_difficulty :\n difficulty of the parent block.\n\n Returns\n -------\n difficulty : `ethereum.base_types.Uint`\n Computed difficulty for a block.\n ")), + Assign( + targets=[ + Name(id='offset', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=2048)), + op=Mult(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=Constant(value=1), + op=Sub(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_timestamp', ctx=Load()), + op=Sub(), + right=Name(id='parent_timestamp', ctx=Load()))], + keywords=[]), + op=FloorDiv(), + right=Constant(value=10))), + UnaryOp( + op=USub(), + operand=Constant(value=99))], + keywords=[]))), + Assign( + targets=[ + Name(id='difficulty', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='offset', ctx=Load()))), + Assign( + targets=[ + Name(id='num_bomb_periods', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=100000)), + op=Sub(), + right=Constant(value=2))), + If( + test=Compare( + left=Name(id='num_bomb_periods', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='difficulty', ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Name(id='num_bomb_periods', ctx=Load())))], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='difficulty', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/fork.v b/coq/ethereum/spurious_dragon/fork.v new file mode 100644 index 0000000000..9e689c1ca3 --- /dev/null +++ b/coq/ethereum/spurious_dragon/fork.v @@ -0,0 +1,841 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.ethash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.spurious_dragon.__init__. +Require ethereum.spurious_dragon.blocks. +Require ethereum.spurious_dragon.bloom. +Require ethereum.spurious_dragon.fork_types. +Require ethereum.spurious_dragon.state. +Require ethereum.spurious_dragon.transactions. +Require ethereum.spurious_dragon.trie. +Require ethereum.spurious_dragon.utils.message. +Require ethereum.spurious_dragon.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + do* [[ M.get_local ~(| "validate_ommers" |) ~(| + M.get_field ~(| block, "ommers" |), + M.get_field ~(| block, "header" |), + chain + |) ]] in + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "difficulty" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| block, "ommers" |), + M.get_field ~(| chain, "chain_id" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_difficulty" [[ + M.get_local ~(| "calculate_block_difficulty" |) ~(| + M.get_field ~(| header, "number" |), + M.get_field ~(| header, "timestamp" |), + M.get_field ~(| parent_header, "timestamp" |), + M.get_field ~(| parent_header, "difficulty" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| + header + |) ]] in + M.pure tt. + +Definition generate_header_hash_for_pow (header : Header) : M Hash32 := + (* + 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. + *) + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_proof_of_work (header : Header) : M unit := + (* + 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. + *) + do* M.assign "header_hash" [[ + M.get_local ~(| "generate_header_hash_for_pow" |) ~(| + header + |) in + ]] in + do* M.assign "cache" [[ + ethereum.ethash.generate_cache ~(| + M.get_field ~(| header, "number" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (gas_available : Uint) (chain_id : U64) : M Address := + (* + Check if the transaction is includable in the block. + + Parameters + ---------- + tx : + The transaction. + gas_available : + The gas remaining in the block. + chain_id : + The ID of the current chain. + + Returns + ------- + sender_address : + The sender of the transaction. + + Raises + ------ + InvalidBlock : + If the transaction is not includable. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + chain_id, + tx + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (post_state : Bytes32) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (block_gas_limit : Uint) (block_time : U256) (block_difficulty : Uint) (transactions : (* TODO type *)) (ommers : (* TODO type *)) (chain_id : U64) : M ApplyBodyOutput := + (* + 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.) + chain_id : + ID of the executing chain. + + Returns + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "pay_rewards" |) ~(| + state, + block_number, + coinbase, + ommers + |) ]] in + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_ommers (ommers : (* TODO type *)) (block_header : Header) (chain : BlockChain) : M unit := + (* + 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. + *) + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_canonical_blocks" [[ + (* TODO expression *) in + ]] in + do* M.assign "recent_canonical_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition pay_rewards (state : State) (block_number : Uint) (coinbase : Address) (ommers : (* TODO type *)) : M unit := + (* + 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. + *) + do* M.assign "ommer_count" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + ommers + |) + |) in + ]] in + do* M.assign "miner_reward" [[ + (* TODO expression *) in + ]] in + do* [[ state.create_ether ~(| + state, + coinbase, + M.get_local ~(| "miner_reward" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + do* M.assign "gas_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (chain_id : U64) (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_pre155 (tx : Transaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition signing_hash_155 (tx : Transaction) (chain_id : U64) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_block_difficulty (block_number : Uint) (block_timestamp : U256) (parent_timestamp : U256) (parent_difficulty : Uint) : M Uint := + (* + 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. + *) + do* M.assign "offset" [[ + (* TODO expression *) in + ]] in + do* M.assign "difficulty" [[ + (* TODO expression *) in + ]] in + do* M.assign "num_bomb_periods" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/fork_types.ast b/coq/ethereum/spurious_dragon/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/spurious_dragon/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/fork_types.v b/coq/ethereum/spurious_dragon/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/spurious_dragon/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/state.ast b/coq/ethereum/spurious_dragon/state.ast new file mode 100644 index 0000000000..e39d5427ff --- /dev/null +++ b/coq/ethereum/spurious_dragon/state.ast @@ -0,0 +1,1500 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has zero nonce, empty code and zero balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_empty : `bool`\n True if if an account has zero nonce, empty code and zero balance,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_exists_and_is_empty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists and has zero nonce, empty code and zero\n balance.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n exists_and_is_empty : `bool`\n True if an account exists and has zero nonce, empty code and zero\n balance, False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='account', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_account_alive', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether is an account is both in the state and non empty.\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n is_alive : `bool`\n True if the account is alive.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[ + Return( + value=UnaryOp( + op=Not(), + operand=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])])))])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add newly created ether to an account.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to which ether is added.\n amount:\n The amount of ether to be added to the account of interest.\n ')), + FunctionDef( + name='increase_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/state.v b/coq/ethereum/spurious_dragon/state.v new file mode 100644 index 0000000000..3c6bedf8ba --- /dev/null +++ b/coq/ethereum/spurious_dragon/state.v @@ -0,0 +1,562 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.spurious_dragon.fork_types. +Require ethereum.spurious_dragon.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_empty (state : State) (address : Address) : M bool := + (* + Checks if an account has zero nonce, empty code and zero balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_empty : `bool` + True if if an account has zero nonce, empty code and zero balance, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition account_exists_and_is_empty (state : State) (address : Address) : M bool := + (* + Checks if an account exists and has zero nonce, empty code and zero + balance. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + exists_and_is_empty : `bool` + True if an account exists and has zero nonce, empty code and zero + balance, False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_account_alive (state : State) (address : Address) : M bool := + (* + Check whether is an account is both in the state and non empty. + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + is_alive : `bool` + True if the account is alive. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := + (* + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/transactions.ast b/coq/ethereum/spurious_dragon/transactions.ast new file mode 100644 index 0000000000..19d5c9707f --- /dev/null +++ b/coq/ethereum/spurious_dragon/transactions.ast @@ -0,0 +1,106 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + ClassDef( + name='Transaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/transactions.v b/coq/ethereum/spurious_dragon/transactions.v new file mode 100644 index 0000000000..d37ebdefa3 --- /dev/null +++ b/coq/ethereum/spurious_dragon/transactions.v @@ -0,0 +1,13 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.spurious_dragon.fork_types. diff --git a/coq/ethereum/spurious_dragon/trie.ast b/coq/ethereum/spurious_dragon/trie.ast new file mode 100644 index 0000000000..9c29e05578 --- /dev/null +++ b/coq/ethereum/spurious_dragon/trie.ast @@ -0,0 +1,1618 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.tangerine_whistle', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.Extended`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/trie.v b/coq/ethereum/spurious_dragon/trie.v new file mode 100644 index 0000000000..3b45315972 --- /dev/null +++ b/coq/ethereum/spurious_dragon/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.Extended` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/utils/__init__.ast b/coq/ethereum/spurious_dragon/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/spurious_dragon/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/utils/__init__.v b/coq/ethereum/spurious_dragon/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/spurious_dragon/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/spurious_dragon/utils/address.ast b/coq/ethereum/spurious_dragon/utils/address.ast new file mode 100644 index 0000000000..9bc369a43a --- /dev/null +++ b/coq/ethereum/spurious_dragon/utils/address.ast @@ -0,0 +1,139 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this spurious dragon version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `ethereum.spurious_dragon.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/utils/address.v b/coq/ethereum/spurious_dragon/utils/address.v new file mode 100644 index 0000000000..ae256d9d48 --- /dev/null +++ b/coq/ethereum/spurious_dragon/utils/address.v @@ -0,0 +1,75 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this spurious dragon version of +specification. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.spurious_dragon.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.spurious_dragon.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/utils/hexadecimal.ast b/coq/ethereum/spurious_dragon/utils/hexadecimal.ast new file mode 100644 index 0000000000..84a0174c53 --- /dev/null +++ b/coq/ethereum/spurious_dragon/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to\nSpurious Dragon types.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/utils/hexadecimal.v b/coq/ethereum/spurious_dragon/utils/hexadecimal.v new file mode 100644 index 0000000000..8e69a91904 --- /dev/null +++ b/coq/ethereum/spurious_dragon/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Spurious Dragon types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.spurious_dragon.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/utils/message.ast b/coq/ethereum/spurious_dragon/utils/message.ast new file mode 100644 index 0000000000..000559007d --- /dev/null +++ b/coq/ethereum/spurious_dragon/utils/message.ast @@ -0,0 +1,234 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this spurious dragon version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True)]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n\n Returns\n -------\n message: `ethereum.spurious_dragon.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/utils/message.v b/coq/ethereum/spurious_dragon/utils/message.v new file mode 100644 index 0000000000..1a47b5c972 --- /dev/null +++ b/coq/ethereum/spurious_dragon/utils/message.v @@ -0,0 +1,57 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this spurious dragon version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.spurious_dragon.fork_types. +Require ethereum.spurious_dragon.state. +Require ethereum.spurious_dragon.vm. +Require ethereum.spurious_dragon.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + + Returns + ------- + message: `ethereum.spurious_dragon.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/__init__.ast b/coq/ethereum/spurious_dragon/vm/__init__.ast new file mode 100644 index 0000000000..05b908b1df --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/__init__.ast @@ -0,0 +1,501 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='account_exists_and_is_empty')], + level=2), + ImportFrom( + module='precompiled_contracts', + names=[ + alias(name='RIPEMD160_ADDRESS')], + level=1), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + If( + test=Compare( + left=Name(id='RIPEMD160_ADDRESS', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='RIPEMD160_ADDRESS', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/__init__.v b/coq/ethereum/spurious_dragon/vm/__init__.v new file mode 100644 index 0000000000..de947ecf97 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/__init__.v @@ -0,0 +1,72 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.spurious_dragon.blocks. +Require ethereum.spurious_dragon.fork_types. +Require ethereum.spurious_dragon.state. +Require ethereum.spurious_dragon.vm.precompiled_contracts. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "touched_accounts" |), "update" |) ~(| + M.get_field ~(| child_evm, "touched_accounts" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + (* TODO statement *) + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/exceptions.ast b/coq/ethereum/spurious_dragon/vm/exceptions.ast new file mode 100644 index 0000000000..3194c3c232 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/exceptions.ast @@ -0,0 +1,125 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/exceptions.v b/coq/ethereum/spurious_dragon/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/spurious_dragon/vm/gas.ast b/coq/ethereum/spurious_dragon/vm/gas.ast new file mode 100644 index 0000000000..0582fb1566 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/gas.ast @@ -0,0 +1,801 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=50)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXTERNAL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BALANCE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=400)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='REFUND_SELF_DESTRUCT', ctx=Store())], + value=Constant(value=24000)), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_left', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='memory_cost', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='extra_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='call_stipend', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Expr( + value=Constant(value='\n Calculates the MessageCallGas (cost and stipend) for\n executing call Opcodes.\n\n Parameters\n ----------\n value:\n The amount of `ETH` that needs to be transferred.\n gas :\n The amount of gas provided to the message-call.\n gas_left :\n The amount of gas left in the current frame.\n memory_cost :\n The amount needed to extend the memory in the current frame.\n extra_gas :\n The amount of gas needed for transferring value + creating a new\n account inside a message call.\n call_stipend :\n The amount of stipend provided to a message call to execute code while\n transferring value(ETH).\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='call_stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='call_stipend', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='extra_gas', ctx=Load()), + op=Add(), + right=Name(id='memory_cost', ctx=Load()))]), + body=[ + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='gas', ctx=Load()), + Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='gas_left', ctx=Load()), + op=Sub(), + right=Name(id='memory_cost', ctx=Load())), + op=Sub(), + right=Name(id='extra_gas', ctx=Load()))], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load())), + FunctionDef( + name='max_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the maximum gas that is allowed for making a message call\n\n Parameters\n ----------\n gas :\n The amount of gas provided to the message-call.\n\n Returns\n -------\n max_allowed_message_call_gas: `ethereum.base_types.Uint`\n The maximum gas allowed for making the message-call.\n ')), + Return( + value=BinOp( + left=Name(id='gas', ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='gas', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]))))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/gas.v b/coq/ethereum/spurious_dragon/vm/gas.v new file mode 100644 index 0000000000..aad2c0de80 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/gas.v @@ -0,0 +1,171 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (value : U256) (gas : Uint) (gas_left : Uint) (memory_cost : Uint) (extra_gas : Uint) (call_stipend : Uint) : M MessageCallGas := + (* + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "gas" [[ + M.get_local ~(| "min" |) ~(| + gas, + M.get_local ~(| "max_message_call_gas" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition max_message_call_gas (gas : Uint) : M Uint := + (* + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/instructions/__init__.ast b/coq/ethereum/spurious_dragon/vm/instructions/__init__.ast new file mode 100644 index 0000000000..0931c390c8 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/__init__.ast @@ -0,0 +1,1648 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='DIFFICULTY', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIFFICULTY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/instructions/__init__.v b/coq/ethereum/spurious_dragon/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/spurious_dragon/vm/instructions/arithmetic.ast b/coq/ethereum/spurious_dragon/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/instructions/arithmetic.v b/coq/ethereum/spurious_dragon/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..c9161c970e --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/instructions/bitwise.ast b/coq/ethereum/spurious_dragon/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..73dc9f4a45 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/bitwise.ast @@ -0,0 +1,418 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/instructions/bitwise.v b/coq/ethereum/spurious_dragon/vm/instructions/bitwise.v new file mode 100644 index 0000000000..fb45d69e5b --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/bitwise.v @@ -0,0 +1,196 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/instructions/block.ast b/coq/ethereum/spurious_dragon/vm/instructions/block.ast new file mode 100644 index 0000000000..cc66857e82 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/block.ast @@ -0,0 +1,437 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's difficulty onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/instructions/block.v b/coq/ethereum/spurious_dragon/vm/instructions/block.v new file mode 100644 index 0000000000..93b8b65618 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/block.v @@ -0,0 +1,213 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition difficulty (evm : Evm) : M unit := + (* + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/instructions/comparison.ast b/coq/ethereum/spurious_dragon/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/instructions/comparison.v b/coq/ethereum/spurious_dragon/vm/instructions/comparison.v new file mode 100644 index 0000000000..9ffa78c95f --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/instructions/control_flow.ast b/coq/ethereum/spurious_dragon/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/instructions/control_flow.v b/coq/ethereum/spurious_dragon/vm/instructions/control_flow.v new file mode 100644 index 0000000000..dcef66f3fb --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.exceptions. +Require ethereum.spurious_dragon.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/instructions/environment.ast b/coq/ethereum/spurious_dragon/vm/instructions/environment.ast new file mode 100644 index 0000000000..15f88ad9cc --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/environment.ast @@ -0,0 +1,1199 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BALANCE'), + alias(name='GAS_BASE'), + alias(name='GAS_COPY'), + alias(name='GAS_EXTERNAL'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BALANCE', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_EXTERNAL', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_EXTERNAL', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/instructions/environment.v b/coq/ethereum/spurious_dragon/vm/instructions/environment.v new file mode 100644 index 0000000000..676093a15c --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/environment.v @@ -0,0 +1,552 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.spurious_dragon.state. +Require ethereum.spurious_dragon.utils.address. +Require ethereum.spurious_dragon.vm.memory. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BALANCE + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_EXTERNAL + |) ]] in + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/instructions/keccak.ast b/coq/ethereum/spurious_dragon/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/instructions/keccak.v b/coq/ethereum/spurious_dragon/vm/instructions/keccak.v new file mode 100644 index 0000000000..b1428ca4d7 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.memory. +Require ethereum.spurious_dragon.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/instructions/log.ast b/coq/ethereum/spurious_dragon/vm/instructions/log.ast new file mode 100644 index 0000000000..d3bf292c44 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/log.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/instructions/log.v b/coq/ethereum/spurious_dragon/vm/instructions/log.v new file mode 100644 index 0000000000..1759e4d4ba --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/log.v @@ -0,0 +1,77 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.spurious_dragon.blocks. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.memory. +Require ethereum.spurious_dragon.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/instructions/memory.ast b/coq/ethereum/spurious_dragon/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/instructions/memory.v b/coq/ethereum/spurious_dragon/vm/instructions/memory.v new file mode 100644 index 0000000000..43f96f693f --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.memory. +Require ethereum.spurious_dragon.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/instructions/stack.ast b/coq/ethereum/spurious_dragon/vm/instructions/stack.ast new file mode 100644 index 0000000000..95cfc0b6cf --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/stack.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/instructions/stack.v b/coq/ethereum/spurious_dragon/vm/instructions/stack.v new file mode 100644 index 0000000000..04e12c60a6 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/stack.v @@ -0,0 +1,153 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.exceptions. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/instructions/storage.ast b/coq/ethereum/spurious_dragon/vm/instructions/storage.ast new file mode 100644 index 0000000000..7ce9b2f17f --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/storage.ast @@ -0,0 +1,278 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_SLOAD', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_UPDATE', ctx=Load()))]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/instructions/storage.v b/coq/ethereum/spurious_dragon/vm/instructions/storage.v new file mode 100644 index 0000000000..b4589d1612 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/storage.v @@ -0,0 +1,108 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.spurious_dragon.state. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_SLOAD + |) ]] in + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/instructions/system.ast b/coq/ethereum/spurious_dragon/vm/instructions/system.ast new file mode 100644 index 0000000000..a198f7a173 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/system.ast @@ -0,0 +1,2058 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='is_account_alive'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL'), + alias(name='GAS_CALL_VALUE'), + alias(name='GAS_CREATE'), + alias(name='GAS_NEW_ACCOUNT'), + alias(name='GAS_SELF_DESTRUCT'), + alias(name='GAS_SELF_DESTRUCT_NEW_ACCOUNT'), + alias(name='GAS_ZERO'), + alias(name='REFUND_SELF_DESTRUCT'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas'), + alias(name='max_message_call_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='create_message_gas', ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])])]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[])]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SELF_DESTRUCT', ctx=Load())), + If( + test=BoolOp( + op=And(), + values=[ + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_account_alive', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[])), + Compare( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='refunded_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load())), + While( + test=Compare( + left=Name(id='parent_evm', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='refunded_accounts', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='originator', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='refunded_accounts', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Name(id='REFUND_SELF_DESTRUCT', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='beneficiary', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='GAS_CALL', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/instructions/system.v b/coq/ethereum/spurious_dragon/vm/instructions/system.v new file mode 100644 index 0000000000..a935f84563 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/instructions/system.v @@ -0,0 +1,523 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.spurious_dragon.fork_types. +Require ethereum.spurious_dragon.state. +Require ethereum.spurious_dragon.utils.address. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.memory. +Require ethereum.spurious_dragon.vm.stack. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "create_message_gas" [[ + gas.max_message_call_gas ~(| + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) in + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_local ~(| "create_message_gas" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_SELF_DESTRUCT in + ]] in + (* TODO statement *) + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "refunded_accounts" [[ + M.get_field ~(| evm, "accounts_to_delete" |) in + ]] in + do* M.assign "parent_evm" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "parent_evm" |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO statement *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + gas.GAS_CALL + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/interpreter.ast b/coq/ethereum/spurious_dragon/vm/interpreter.ast new file mode 100644 index 0000000000..8587625def --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/interpreter.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Iterable'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_exists_and_is_empty'), + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='increment_nonce'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidOpcode'), + alias(name='OutOfGasError'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_CODE_SIZE', ctx=Store())], + value=Constant(value=24576)), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `touched_accounts`: Accounts that have been touched.\n 6. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='touched_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='account_exists_and_is_empty', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='Address', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='touched_accounts', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='touched_accounts', + value=Name(id='touched_accounts', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.spurious_dragon.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_CODE_SIZE', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[])], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.spurious_dragon.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='touched_accounts', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='error', + value=Constant(value=None))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/interpreter.v b/coq/ethereum/spurious_dragon/vm/interpreter.v new file mode 100644 index 0000000000..c2df93da24 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/interpreter.v @@ -0,0 +1,169 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.spurious_dragon.blocks. +Require ethereum.spurious_dragon.fork_types. +Require ethereum.spurious_dragon.state. +Require ethereum.spurious_dragon.vm. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.precompiled_contracts.mapping. +Require ethereum.spurious_dragon.vm.__init__. +Require ethereum.spurious_dragon.vm.exceptions. +Require ethereum.spurious_dragon.vm.instructions. +Require ethereum.spurious_dragon.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.spurious_dragon.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.spurious_dragon.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/memory.ast b/coq/ethereum/spurious_dragon/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/memory.v b/coq/ethereum/spurious_dragon/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.ast b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..2ac4916772 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,52 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.v b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..cad0c38372 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.spurious_dragon.utils.hexadecimal. diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..c07f765497 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.spurious_dragon.vm. +Require ethereum.spurious_dragon.vm.gas. +Require ethereum.spurious_dragon.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/identity.ast b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/identity.v b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..4ec9a2cd0a --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.spurious_dragon.vm. +Require ethereum.spurious_dragon.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.ast b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..de162645ff --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,65 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.v b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..d0224bfeb5 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/mapping.v @@ -0,0 +1,22 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.spurious_dragon.fork_types. +Require ethereum.spurious_dragon.vm.precompiled_contracts.__init__. +Require ethereum.spurious_dragon.vm.precompiled_contracts.ecrecover. +Require ethereum.spurious_dragon.vm.precompiled_contracts.identity. +Require ethereum.spurious_dragon.vm.precompiled_contracts.ripemd160. +Require ethereum.spurious_dragon.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.ast b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.v b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/runtime.ast b/coq/ethereum/spurious_dragon/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/runtime.v b/coq/ethereum/spurious_dragon/vm/runtime.v new file mode 100644 index 0000000000..30aa2dc40d --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.spurious_dragon.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/spurious_dragon/vm/stack.ast b/coq/ethereum/spurious_dragon/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/spurious_dragon/vm/stack.v b/coq/ethereum/spurious_dragon/vm/stack.v new file mode 100644 index 0000000000..2d22e100f8 --- /dev/null +++ b/coq/ethereum/spurious_dragon/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.spurious_dragon.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/__init__.ast b/coq/ethereum/tangerine_whistle/__init__.ast new file mode 100644 index 0000000000..11b245cd21 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/__init__.ast @@ -0,0 +1,18 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe Tangerine Whistle fork is the first of two forks responding to a\ndenial-of-service attack on the Ethereum network. It tunes the price of various\nEVM instructions, and reduces the state size by removing a number of empty\naccounts.\n')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + Assign( + targets=[ + Name(id='FORK_CRITERIA', ctx=Store())], + value=Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=2463000)], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/__init__.v b/coq/ethereum/tangerine_whistle/__init__.v new file mode 100644 index 0000000000..f98aa35940 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/__init__.v @@ -0,0 +1,9 @@ +(* Generated *) +(* +The Tangerine Whistle fork is the first of two forks responding to a +denial-of-service attack on the Ethereum network. It tunes the price of various +EVM instructions, and reduces the state size by removing a number of empty +accounts. +*) + +Require ethereum.fork_criteria. diff --git a/coq/ethereum/tangerine_whistle/blocks.ast b/coq/ethereum/tangerine_whistle/blocks.ast new file mode 100644 index 0000000000..dce2db5da0 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/blocks.ast @@ -0,0 +1,218 @@ +Module( + body=[ + Expr( + value=Constant(value='\nA `Block` is a single link in the chain that is Ethereum. Each `Block` contains\na `Header` and zero or more transactions. Each `Header` contains associated\nmetadata like the block number, parent block hash, and how much gas was\nconsumed by its transactions.\n\nTogether, these blocks form a cryptographically secure journal recording the\nhistory of all state transitions that have happened since the genesis of the\nchain.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Header portion of a block on the chain.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mix_digest', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Block', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A complete block.\n ')), + AnnAssign( + target=Name(id='header', ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Log', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Data record produced during the execution of a transaction.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='topics', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hash32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Receipt', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Result of a transaction.\n ')), + AnnAssign( + target=Name(id='post_state', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='cumulative_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/blocks.v b/coq/ethereum/tangerine_whistle/blocks.v new file mode 100644 index 0000000000..0186334e6d --- /dev/null +++ b/coq/ethereum/tangerine_whistle/blocks.v @@ -0,0 +1,20 @@ +(* Generated *) +(* +A `Block` is a single link in the chain that is Ethereum. Each `Block` contains +a `Header` and zero or more transactions. Each `Header` contains associated +metadata like the block number, parent block hash, and how much gas was +consumed by its transactions. + +Together, these blocks form a cryptographically secure journal recording the +history of all state transitions that have happened since the genesis of the +chain. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.tangerine_whistle.fork_types. +Require ethereum.tangerine_whistle.transactions. diff --git a/coq/ethereum/tangerine_whistle/bloom.ast b/coq/ethereum/tangerine_whistle/bloom.ast new file mode 100644 index 0000000000..3fa9f742f5 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/bloom.ast @@ -0,0 +1,208 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Logs Bloom\n^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis modules defines functions for calculating bloom filters of logs. For the\ngeneral theory of bloom filters see e.g. `Wikipedia\n`_. Bloom filters are used to allow\nfor efficient searching of logs by address and/or topic, by rapidly\neliminating blocks and receipts from their search.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Bloom')], + level=1), + FunctionDef( + name='add_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bloom', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='bloom_entry', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a bloom entry to the bloom filter (`bloom`).\n\n The number of hash functions used is 3. They are calculated by taking the\n least significant 11 bits from the first 3 16-bit words of the\n `keccak_256()` hash of `bloom_entry`.\n\n Parameters\n ----------\n bloom :\n The bloom filter.\n bloom_entry :\n An entry which is to be added to bloom filter.\n ')), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='bloom_entry', ctx=Load())], + keywords=[])), + For( + target=Name(id='idx', ctx=Store()), + iter=Tuple( + elts=[ + Constant(value=0), + Constant(value=2), + Constant(value=4)], + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='bit_to_set', ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='hash', ctx=Load()), + slice=Slice( + lower=Name(id='idx', ctx=Load()), + upper=BinOp( + left=Name(id='idx', ctx=Load()), + op=Add(), + right=Constant(value=2))), + ctx=Load())], + keywords=[]), + op=BitAnd(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2047)], + keywords=[]))), + Assign( + targets=[ + Name(id='bit_index', ctx=Store())], + value=BinOp( + left=Constant(value=2047), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='bit_to_set', ctx=Load())], + keywords=[]))), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=FloorDiv(), + right=Constant(value=8))), + Assign( + targets=[ + Name(id='bit_value', ctx=Store())], + value=BinOp( + left=Constant(value=1), + op=LShift(), + right=BinOp( + left=Constant(value=7), + op=Sub(), + right=BinOp( + left=Name(id='bit_index', ctx=Load()), + op=Mod(), + right=Constant(value=8))))), + Assign( + targets=[ + Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='bloom', ctx=Load()), + slice=Name(id='byte_index', ctx=Load()), + ctx=Load()), + op=BitOr(), + right=Name(id='bit_value', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the logs bloom from a list of log entries.\n\n The address and each topic of a log are added to the bloom filter.\n\n Parameters\n ----------\n logs :\n List of logs for which the logs bloom is to be obtained.\n\n Returns\n -------\n logs_bloom : `Bloom`\n The logs bloom obtained which is 256 bytes with some bits set as per\n the caller address and the log topics.\n ')), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Constant(value=256))], + keywords=[]), + simple=1), + For( + target=Name(id='log', ctx=Store()), + iter=Name(id='logs', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Attribute( + value=Name(id='log', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[])), + For( + target=Name(id='topic', ctx=Store()), + iter=Attribute( + value=Name(id='log', ctx=Load()), + attr='topics', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_to_bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load()), + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Name(id='bloom', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/bloom.v b/coq/ethereum/tangerine_whistle/bloom.v new file mode 100644 index 0000000000..4984ab00e1 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/bloom.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Ethereum Logs Bloom +^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This modules defines functions for calculating bloom filters of logs. For the +general theory of bloom filters see e.g. `Wikipedia +`_. Bloom filters are used to allow +for efficient searching of logs by address and/or topic, by rapidly +eliminating blocks and receipts from their search. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.tangerine_whistle.blocks. +Require ethereum.tangerine_whistle.fork_types. + +Definition add_to_bloom (bloom : bytearray) (bloom_entry : bytes) : M unit := + (* + Add a bloom entry to the bloom filter (`bloom`). + + The number of hash functions used is 3. They are calculated by taking the + least significant 11 bits from the first 3 16-bit words of the + `keccak_256()` hash of `bloom_entry`. + + Parameters + ---------- + bloom : + The bloom filter. + bloom_entry : + An entry which is to be added to bloom filter. + *) + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + bloom_entry + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition logs_bloom (logs : (* TODO type *)) : M Bloom := + (* + Obtain the logs bloom from a list of log entries. + + The address and each topic of a log are added to the bloom filter. + + Parameters + ---------- + logs : + List of logs for which the logs bloom is to be obtained. + + Returns + ------- + logs_bloom : `Bloom` + The logs bloom obtained which is 256 bytes with some bits set as per + the caller address and the log topics. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/fork.ast b/coq/ethereum/tangerine_whistle/fork.ast new file mode 100644 index 0000000000..2305e94da0 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/fork.ast @@ -0,0 +1,2908 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification\n^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEntry point for the Ethereum specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.ethash', + names=[ + alias(name='dataset_size'), + alias(name='generate_cache'), + alias(name='hashimoto_light')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock'), + alias(name='InvalidSenderError')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + names=[ + alias(name='vm')], + level=1), + ImportFrom( + module='blocks', + names=[ + alias(name='Block'), + alias(name='Header'), + alias(name='Log'), + alias(name='Receipt')], + level=1), + ImportFrom( + module='bloom', + names=[ + alias(name='logs_bloom')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=1), + ImportFrom( + module='state', + names=[ + alias(name='State'), + alias(name='create_ether'), + alias(name='destroy_account'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance'), + alias(name='state_root')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='TX_BASE_COST'), + alias(name='TX_CREATE_COST'), + alias(name='TX_DATA_COST_PER_NON_ZERO'), + alias(name='TX_DATA_COST_PER_ZERO'), + alias(name='Transaction')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='Trie'), + alias(name='root'), + alias(name='trie_set')], + level=1), + ImportFrom( + module='utils.message', + names=[ + alias(name='prepare_message')], + level=1), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='process_message_call')], + level=1), + Assign( + targets=[ + Name(id='BLOCK_REWARD', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Constant(value=5), + op=Mult(), + right=BinOp( + left=Constant(value=10), + op=Pow(), + right=Constant(value=18)))], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=131072)], + keywords=[])), + Assign( + targets=[ + Name(id='MAX_OMMER_DEPTH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + ClassDef( + name='BlockChain', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n History and current state of the block chain.\n ')), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Block', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain_id', ctx=Store()), + annotation=Name(id='U64', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_fork', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Transforms the state from the previous hard fork (`old`) into the block\n chain object for this hard fork and returns it.\n\n When forks need to implement an irregular state transition, this function\n is used to handle the irregularity. See the :ref:`DAO Fork ` for\n an example.\n\n Parameters\n ----------\n old :\n Previous block chain object.\n\n Returns\n -------\n new : `BlockChain`\n Upgraded block chain object for this hard fork.\n ')), + Return( + value=Name(id='old', ctx=Load()))], + decorator_list=[], + returns=Name(id='BlockChain', ctx=Load())), + FunctionDef( + name='get_last_256_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain the list of hashes of the previous 256 blocks in order of\n increasing block number.\n\n This function will return less hashes for the first 256 blocks.\n\n The ``BLOCKHASH`` opcode needs to access the latest hashes on the chain,\n therefore this function retrieves them.\n\n Parameters\n ----------\n chain :\n History and current state.\n\n Returns\n -------\n recent_block_hashes : `List[Hash32]`\n Hashes of the recent 256 blocks in order of increasing block number.\n ')), + Assign( + targets=[ + Name(id='recent_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load())), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='recent_blocks', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_block_hashes', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prev_block_hash', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='parent_hash', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='prev_block_hash', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='most_recent_block_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Name(id='recent_blocks', ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='recent_block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='most_recent_block_hash', ctx=Load())], + keywords=[])), + Return( + value=Name(id='recent_block_hashes', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load())), + arg( + arg='block', + annotation=Name(id='Block', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Attempts to apply a block to an existing block chain.\n\n All parts of the block's contents need to be verified before being added\n to the chain. Blocks are verified by ensuring that the contents of the\n block make logical sense with the contents of the parent block. The\n information in the block's header must also match the corresponding\n information in the block.\n\n To implement Ethereum, in theory clients are only required to store the\n most recent 255 blocks of the chain since as far as execution is\n concerned, only those blocks are accessed. Practically, however, clients\n should store more blocks to handle reorgs.\n\n Parameters\n ----------\n chain :\n History and current state.\n block :\n Block to apply to `chain`.\n ")), + Assign( + targets=[ + Name(id='parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='parent_header', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='validate_ommers', ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + Name(id='chain', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='apply_body_output', ctx=Store())], + value=Call( + func=Name(id='apply_body', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='state', + ctx=Load()), + Call( + func=Name(id='get_last_256_block_hashes', ctx=Load()), + args=[ + Name(id='chain', ctx=Load())], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidBlock', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_gas_used', + ctx=Load()), + conversion=-1), + Constant(value=' != '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='transactions_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='transactions_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='state_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='state_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='receipt_root', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='receipt_root', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='apply_body_output', ctx=Load()), + attr='block_logs_bloom', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='bloom', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=255)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=255))), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='validate_header', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='parent_header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a block header.\n\n In order to consider a block's header valid, the logic for the\n quantities in the header should match the logic for the block itself.\n For example the header timestamp should be greater than the block's parent\n timestamp because the block was created *after* the parent block.\n Additionally, the block's number should be directly following the parent\n block's number since it is the next block in the sequence.\n\n Parameters\n ----------\n header :\n Header to check for correctness.\n parent_header :\n Parent Header of the header to check for correctness\n ")), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + BinOp( + left=Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='check_gas_limit', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=32)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_difficulty', ctx=Store())], + value=Call( + func=Name(id='calculate_block_difficulty', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='parent_header', ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_difficulty', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='block_parent_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parent_header', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='block_parent_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='validate_proof_of_work', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generate_header_hash_for_pow', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Generate rlp hash of the header which is to be used for Proof-of-Work\n verification.\n\n In other words, the PoW artefacts `mix_digest` and `nonce` are ignored\n while calculating this hash.\n\n A particular PoW is valid for a single hash, that hash is computed by\n this function. The `nonce` and `mix_digest` are omitted from this hash\n because they are being changed by miners in their search for a sufficient\n proof-of-work.\n\n Parameters\n ----------\n header :\n The header object for which the hash is to be generated.\n\n Returns\n -------\n hash : `Hash32`\n The PoW valid rlp hash of the passed in header.\n ')), + Assign( + targets=[ + Name(id='header_data_without_pow_artefacts', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='parent_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='ommers_hash', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='state_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='transactions_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='receipt_root', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='bloom', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='extra_data', + ctx=Load())], + ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='header_data_without_pow_artefacts', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='validate_proof_of_work', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the Proof of Work constraints.\n\n In order to verify that a miner's proof-of-work is valid for a block, a\n ``mix-digest`` and ``result`` are calculated using the ``hashimoto_light``\n hash function. The mix digest is a hash of the header and the nonce that\n is passed through and it confirms whether or not proof-of-work was done\n on the correct block. The result is the actual hash value of the block.\n\n Parameters\n ----------\n header :\n Header of interest.\n ")), + Assign( + targets=[ + Name(id='header_hash', ctx=Store())], + value=Call( + func=Name(id='generate_header_hash_for_pow', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='cache', ctx=Store())], + value=Call( + func=Name(id='generate_cache', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='mix_digest', ctx=Store()), + Name(id='result', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='hashimoto_light', ctx=Load()), + args=[ + Name(id='header_hash', ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + Name(id='cache', ctx=Load()), + Call( + func=Name(id='dataset_size', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='mix_digest', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='mix_digest', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='limit', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='limit', ctx=Load()), + op=FloorDiv(), + right=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load()))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if the transaction is includable in the block.\n\n Parameters\n ----------\n tx :\n The transaction.\n gas_available :\n The gas remaining in the block.\n\n Returns\n -------\n sender_address :\n The sender of the transaction.\n\n Raises\n ------\n InvalidBlock :\n If the transaction is not includable.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='gas_available', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='recover_sender', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + Return( + value=Name(id='sender_address', ctx=Load()))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load())), + arg( + arg='post_state', + annotation=Name(id='Bytes32', ctx=Load())), + arg( + arg='cumulative_gas_used', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='logs', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Make the receipt for a transaction that was executed.\n\n Parameters\n ----------\n tx :\n The executed transaction.\n post_state :\n The state root immediately after this transaction.\n cumulative_gas_used :\n The total gas used so far in the block after the transaction was\n executed.\n logs :\n The logs produced by the transaction.\n\n Returns\n -------\n receipt :\n The receipt for the transaction.\n ')), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='Receipt', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='post_state', + value=Name(id='post_state', ctx=Load())), + keyword( + arg='cumulative_gas_used', + value=Name(id='cumulative_gas_used', ctx=Load())), + keyword( + arg='bloom', + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='logs', ctx=Load())], + keywords=[])), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load()))])), + Return( + value=Name(id='receipt', ctx=Load()))], + decorator_list=[], + returns=Name(id='Receipt', ctx=Load())), + ClassDef( + name='ApplyBodyOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output from applying the block body to the present state.\n\n Contains the following:\n\n block_gas_used : `ethereum.base_types.Uint`\n Gas used for executing all transactions.\n transactions_root : `ethereum.fork_types.Root`\n Trie root of all the transactions in the block.\n receipt_root : `ethereum.fork_types.Root`\n Trie root of all the receipts in the block.\n block_logs_bloom : `Bloom`\n Logs bloom of all the logs included in all the transactions of the\n block.\n state_root : `ethereum.fork_types.Root`\n State root after all transactions have been executed.\n ')), + AnnAssign( + target=Name(id='block_gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_logs_bloom', ctx=Store()), + annotation=Name(id='Bloom', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Root', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_hashes', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_time', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='block_difficulty', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='transactions', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a block.\n\n Many of the contents of a block are stored in data structures called\n tries. There is a transactions trie which is similar to a ledger of the\n transactions stored in the current block. There is also a receipts trie\n which stores the results of executing a transaction, like the post state\n and gas used. This function creates and executes the block that is to be\n added to the chain.\n\n Parameters\n ----------\n state :\n Current account state.\n block_hashes :\n List of hashes of the previous 256 blocks in the order of\n increasing block number.\n coinbase :\n Address of account which receives block reward and transaction fees.\n block_number :\n Position of the block within the chain.\n block_gas_limit :\n Initial amount of gas available for execution in this block.\n block_time :\n Time the block was produced, measured in seconds since the epoch.\n block_difficulty :\n Difficulty of the block.\n transactions :\n Transactions included in the block.\n ommers :\n Headers of ancestor blocks which are not direct parents (formerly\n uncles.)\n\n Returns\n -------\n apply_body_output : `ApplyBodyOutput`\n Output of applying the block body to the state.\n ')), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + AnnAssign( + target=Name(id='transactions_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='receipts_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))]), + simple=1), + AnnAssign( + target=Name(id='block_logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='transactions', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='tx', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Call( + func=Name(id='check_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='gas_available', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='origin', + value=Name(id='sender_address', ctx=Load())), + keyword( + arg='block_hashes', + value=Name(id='block_hashes', ctx=Load())), + keyword( + arg='coinbase', + value=Name(id='coinbase', ctx=Load())), + keyword( + arg='number', + value=Name(id='block_number', ctx=Load())), + keyword( + arg='gas_limit', + value=Name(id='block_gas_limit', ctx=Load())), + keyword( + arg='gas_price', + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load())), + keyword( + arg='time', + value=Name(id='block_time', ctx=Load())), + keyword( + arg='difficulty', + value=Name(id='block_difficulty', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load()))])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='gas_used', ctx=Store()), + Name(id='logs', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='process_transaction', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_used', ctx=Load())), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Name(id='make_receipt', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[]), + BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load())), + Name(id='logs', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Name(id='logs', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='pay_rewards', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='block_number', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='ommers', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Name(id='logs_bloom', ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='ApplyBodyOutput', ctx=Load()), + args=[ + Name(id='block_gas_used', ctx=Load()), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[]), + Call( + func=Name(id='root', ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[]), + Name(id='block_logs_bloom', ctx=Load()), + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='ApplyBodyOutput', ctx=Load())), + FunctionDef( + name='validate_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + arg( + arg='block_header', + annotation=Name(id='Header', ctx=Load())), + arg( + arg='chain', + annotation=Name(id='BlockChain', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the ommers mentioned in the block.\n\n An ommer block is a block that wasn't canonically added to the\n blockchain because it wasn't validated as fast as the canonical block\n but was mined at the same time.\n\n To be considered valid, the ommers must adhere to the rules defined in\n the Ethereum protocol. The maximum amount of ommers is 2 per block and\n there cannot be duplicate ommers in a block. Many of the other ommer\n constraints are listed in the in-line comments of this function.\n\n Parameters\n ----------\n ommers :\n List of ommers mentioned in the current block.\n block_header:\n The header of current block.\n chain :\n History and current state.\n ")), + Assign( + targets=[ + Name(id='block_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='block_header', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='ommers_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return()], + orelse=[]), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_parent_header', ctx=Store())], + value=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + op=Sub(), + right=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load())), + Expr( + value=Call( + func=Name(id='validate_header', ctx=Load()), + args=[ + Name(id='ommer', ctx=Load()), + Name(id='ommer_parent_header', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=2)]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommers_hashes', ctx=Store())], + value=ListComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + ifs=[], + is_async=0)])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Name(id='set', ctx=Load()), + args=[ + Name(id='ommers_hashes', ctx=Load())], + keywords=[])], + keywords=[])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='recent_canonical_blocks', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='chain', ctx=Load()), + attr='blocks', + ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=BinOp( + left=Name(id='MAX_OMMER_DEPTH', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + ctx=Load())), + Assign( + targets=[ + Name(id='recent_canonical_block_hashes', ctx=Store())], + value=SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='recent_ommers_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + simple=1), + For( + target=Name(id='block', ctx=Store()), + iter=Name(id='recent_canonical_blocks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='recent_ommers_hashes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='recent_ommers_hashes', ctx=Load()), + attr='union', + ctx=Load()), + args=[ + SetComp( + elt=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='ommer', ctx=Store()), + iter=Attribute( + value=Name(id='block', ctx=Load()), + attr='ommers', + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='ommer_index', ctx=Store()), + Name(id='ommer', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='ommer_hash', ctx=Store())], + value=Subscript( + value=Name(id='ommers_hashes', ctx=Load()), + slice=Name(id='ommer_index', ctx=Load()), + ctx=Load())), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='block_hash', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='ommer_hash', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='recent_ommers_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='block_header', ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='ommer_age', ctx=Load())]), + Compare( + left=Name(id='ommer_age', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='MAX_OMMER_DEPTH', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='recent_canonical_block_hashes', ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='parent_hash', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='block_header', ctx=Load()), + attr='parent_hash', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pay_rewards', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='coinbase', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='ommers', + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Header', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pay rewards to the block miner as well as the ommers miners.\n\n The miner of the canonical block is rewarded with the predetermined\n block reward, ``BLOCK_REWARD``, plus a variable award based off of the\n number of ommer blocks that were mined around the same time, and included\n in the canonical block's header. An ommer block is a block that wasn't\n added to the canonical blockchain because it wasn't validated as fast as\n the accepted block but was mined at the same time. Although not all blocks\n that are mined are added to the canonical chain, miners are still paid a\n reward for their efforts. This reward is called an ommer reward and is\n calculated based on the number associated with the ommer block that they\n mined.\n\n Parameters\n ----------\n state :\n Current account state.\n block_number :\n Position of the block within the chain.\n coinbase :\n Address of account which receives block reward and transaction fees.\n ommers :\n List of ommers mentioned in the current block.\n ")), + Assign( + targets=[ + Name(id='ommer_count', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='miner_reward', ctx=Store())], + value=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='ommer_count', ctx=Load()), + op=Mult(), + right=BinOp( + left=Name(id='BLOCK_REWARD', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='miner_reward', ctx=Load())], + keywords=[])), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommer_age', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_number', ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='number', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='ommer_miner_reward', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]), + op=Sub(), + right=Name(id='ommer_age', ctx=Load())), + op=Mult(), + right=Name(id='BLOCK_REWARD', ctx=Load())), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='create_ether', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='ommer_miner_reward', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='env', + annotation=Attribute( + value=Name(id='vm', ctx=Load()), + attr='Environment', + ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Execute a transaction against the provided environment.\n\n This function processes the actions needed to execute a transaction.\n It decrements the sender's account after calculating the gas fee and\n refunds them the proper amount after execution. Calling contracts,\n deploying code, and incrementing nonces are all examples of actions that\n happen within this function or from a call made within this function.\n\n Accounts that are marked for deletion are processed and destroyed after\n execution.\n\n Parameters\n ----------\n env :\n Environment for the Ethereum Virtual Machine.\n tx :\n Transaction to execute.\n\n Returns\n -------\n gas_left : `ethereum.base_types.U256`\n Remaining gas after execution.\n logs : `Tuple[ethereum.blocks.Log, ...]`\n Logs generated during execution.\n ")), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='validate_transaction', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Attribute( + value=Name(id='env', ctx=Load()), + attr='origin', + ctx=Load())), + Assign( + targets=[ + Name(id='sender_account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='gas_fee', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])]), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidSenderError', ctx=Load()), + args=[ + Constant(value='not EOA')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='sender_balance_after_gas_fee', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='sender_account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Name(id='gas_fee', ctx=Load()))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='sender_balance_after_gas_fee', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message', ctx=Store())], + value=Call( + func=Name(id='prepare_message', ctx=Load()), + args=[ + Name(id='sender', ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + Name(id='gas', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='process_message_call', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_used', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()))), + Assign( + targets=[ + Name(id='gas_refund', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas_used', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='output', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_refund_amount', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load()), + op=Add(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='transaction_fee', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Name(id='output', ctx=Load()), + attr='gas_left', + ctx=Load())), + op=Sub(), + right=Name(id='gas_refund', ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))), + Assign( + targets=[ + Name(id='total_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='gas_used', ctx=Load()), + op=Sub(), + right=Name(id='gas_refund', ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance_after_refund', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='gas_refund_amount', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender', ctx=Load()), + Name(id='sender_balance_after_refund', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='coinbase_balance_after_mining_fee', ctx=Store())], + value=BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='transaction_fee', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='env', ctx=Load()), + attr='coinbase', + ctx=Load()), + Name(id='coinbase_balance_after_mining_fee', ctx=Load())], + keywords=[])), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='output', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='destroy_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='total_gas_used', ctx=Load()), + Attribute( + value=Name(id='output', ctx=Load()), + attr='logs', + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='validate_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Verifies a transaction.\n\n The gas in a transaction gets used to pay for the intrinsic cost of\n operations, therefore if there is insufficient gas then it would not\n be possible to execute a transaction and it will be declared invalid.\n\n Additionally, the nonce of a transaction must not equal or exceed the\n limit defined in `EIP-2681 `_.\n In practice, defining the limit as ``2**64-1`` has no impact because\n sending ``2**64-1`` transactions is improbable. It's not strictly\n impossible though, ``2**64-1`` transactions is the entire capacity of the\n Ethereum blockchain at 2022 gas limits for a little over 22 years.\n\n Parameters\n ----------\n tx :\n Transaction to validate.\n\n Returns\n -------\n verified : `bool`\n True if the transaction can be executed, or False otherwise.\n ")), + If( + test=Compare( + left=Call( + func=Name(id='calculate_intrinsic_cost', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='U64', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_intrinsic_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas that is charged before execution is started.\n\n The intrinsic cost of the transaction is charged before execution has\n begun. Functions/operations in the EVM cost money to execute so this\n intrinsic cost is for the operations that need to be paid for as part of\n the transaction. Data transfer, for example, is part of this intrinsic\n cost. It costs ether to send data over the wire and that ether is\n accounted for in the intrinsic cost calculated in this function. This\n intrinsic cost must be calculated and paid for before execution in order\n for all operations to be implemented.\n\n Parameters\n ----------\n tx :\n Transaction to compute the intrinsic cost of.\n\n Returns\n -------\n verified : `ethereum.base_types.Uint`\n The intrinsic cost of the transaction.\n ')), + Assign( + targets=[ + Name(id='data_cost', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='byte', ctx=Store()), + iter=Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='byte', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_ZERO', ctx=Load()))], + orelse=[ + AugAssign( + target=Name(id='data_cost', ctx=Store()), + op=Add(), + value=Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Load()))])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Name(id='TX_CREATE_COST', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='create_cost', ctx=Store())], + value=Constant(value=0))]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='TX_BASE_COST', ctx=Load()), + op=Add(), + right=Name(id='data_cost', ctx=Load())), + op=Add(), + right=Name(id='create_cost', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='recover_sender', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Extracts the sender address from a transaction.\n\n The v, r, and s values are the three parts that make up the signature\n of a transaction. In order to recover the sender of a transaction the two\n components needed are the signature (``v``, ``r``, and ``s``) and the\n signing hash of the transaction. The sender's public key can be obtained\n with these two values and therefore the sender address can be retrieved.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n sender : `ethereum.fork_types.Address`\n The address of the account that signed the transaction.\n ")), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='v', ctx=Store()), + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='v', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='r', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='s', + ctx=Load())], + ctx=Load())), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=27)]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=28)])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Name(id='SECP256K1N', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]))])]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Call( + func=Name(id='signing_hash', ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='signing_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='tx', + annotation=Name(id='Transaction', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Compute the hash of a transaction used in the signature.\n\n The values that are used to compute the signing hash set the rules for a\n transaction. For example, signing over the gas sets a limit for the\n amount of money that is allowed to be pulled out of the sender's account.\n\n Parameters\n ----------\n tx :\n Transaction of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the transaction.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='tx', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='to', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='tx', ctx=Load()), + attr='data', + ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='compute_header_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes the hash of a block header.\n\n The header hash of a block is the canonical hash that is used to refer\n to a specific block and completely distinguishes a block from another.\n\n ``keccak256`` is a function that produces a 256 bit hash of any input.\n It also takes in any number of bytes as an input and produces a single\n hash for them. A hash is a completely unique output for a single input.\n So an input corresponds to one unique hash that can be used to identify\n the input exactly.\n\n Prior to using the ``keccak256`` hash function, the header must be\n encoded using the Recursive-Length Prefix. See :ref:`rlp`.\n RLP encoding the header converts it into a space-efficient format that\n allows for easy transfer of data between nodes. The purpose of RLP is to\n encode arbitrarily nested arrays of binary data, and RLP is the primary\n encoding method used to serialize objects in Ethereum's execution layer.\n The only purpose of RLP is to encode structure; encoding specific data\n types (e.g. strings, floats) is left up to higher-order protocols.\n\n Parameters\n ----------\n header :\n Header of interest.\n\n Returns\n -------\n hash : `ethereum.crypto.hash.Hash32`\n Hash of the header.\n ")), + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='check_gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas_limit', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='parent_gas_limit', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Validates the gas limit for a block.\n\n The bounds of the gas limit, ``max_adjustment_delta``, is set as the\n quotient of the parent block's gas limit and the\n ``GAS_LIMIT_ADJUSTMENT_FACTOR``. Therefore, if the gas limit that is\n passed through as a parameter is greater than or equal to the *sum* of\n the parent's gas and the adjustment delta then the limit for gas is too\n high and fails this function's check. Similarly, if the limit is less\n than or equal to the *difference* of the parent's gas and the adjustment\n delta *or* the predefined ``GAS_LIMIT_MINIMUM`` then this function's\n check fails because the gas limit doesn't allow for a sufficient or\n reasonable amount of gas to be used on a block.\n\n Parameters\n ----------\n gas_limit :\n Gas limit to validate.\n\n parent_gas_limit :\n Gas limit of the parent block.\n\n Returns\n -------\n check : `bool`\n True if gas limit constraints are satisfied, False otherwise.\n ")), + Assign( + targets=[ + Name(id='max_adjustment_delta', ctx=Store())], + value=BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=FloorDiv(), + right=Name(id='GAS_LIMIT_ADJUSTMENT_FACTOR', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Add(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + LtE()], + comparators=[ + BinOp( + left=Name(id='parent_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='max_adjustment_delta', ctx=Load()))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='gas_limit', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='GAS_LIMIT_MINIMUM', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_timestamp', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='parent_difficulty', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Computes difficulty of a block using its header and parent header.\n\n The difficulty is determined by the time the block was created after its\n parent. The ``offset`` is calculated using the parent block's difficulty,\n ``parent_difficulty``, and the timestamp between blocks. This offset is\n then added to the parent difficulty and is stored as the ``difficulty``\n variable. If the time between the block and its parent is too short, the\n offset will result in a positive number thus making the sum of\n ``parent_difficulty`` and ``offset`` to be a greater value in order to\n avoid mass forking. But, if the time is long enough, then the offset\n results in a negative value making the block less difficult than\n its parent.\n\n The base standard for a block's difficulty is the predefined value\n set for the genesis block since it has no parent. So, a block\n can't be less difficult than the genesis block, therefore each block's\n difficulty is set to the maximum value between the calculated\n difficulty and the ``GENESIS_DIFFICULTY``.\n\n Parameters\n ----------\n block_number :\n Block number of the block.\n block_timestamp :\n Timestamp of the block.\n parent_timestamp :\n Timestamp of the parent block.\n parent_difficulty :\n difficulty of the parent block.\n\n Returns\n -------\n difficulty : `ethereum.base_types.Uint`\n Computed difficulty for a block.\n ")), + Assign( + targets=[ + Name(id='offset', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=2048)), + op=Mult(), + right=Call( + func=Name(id='max', ctx=Load()), + args=[ + BinOp( + left=Constant(value=1), + op=Sub(), + right=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='block_timestamp', ctx=Load()), + op=Sub(), + right=Name(id='parent_timestamp', ctx=Load()))], + keywords=[]), + op=FloorDiv(), + right=Constant(value=10))), + UnaryOp( + op=USub(), + operand=Constant(value=99))], + keywords=[]))), + Assign( + targets=[ + Name(id='difficulty', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='parent_difficulty', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='offset', ctx=Load()))), + Assign( + targets=[ + Name(id='num_bomb_periods', ctx=Store())], + value=BinOp( + left=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Constant(value=100000)), + op=Sub(), + right=Constant(value=2))), + If( + test=Compare( + left=Name(id='num_bomb_periods', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Name(id='difficulty', ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Name(id='num_bomb_periods', ctx=Load())))], + orelse=[]), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='difficulty', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='MINIMUM_DIFFICULTY', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/fork.v b/coq/ethereum/tangerine_whistle/fork.v new file mode 100644 index 0000000000..916c252f88 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/fork.v @@ -0,0 +1,831 @@ +(* Generated *) +(* +Ethereum Specification +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Entry point for the Ethereum specification. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.ethash. +Require ethereum.exceptions. +Require ethereum.__init__. +Require ethereum.tangerine_whistle.__init__. +Require ethereum.tangerine_whistle.blocks. +Require ethereum.tangerine_whistle.bloom. +Require ethereum.tangerine_whistle.fork_types. +Require ethereum.tangerine_whistle.state. +Require ethereum.tangerine_whistle.transactions. +Require ethereum.tangerine_whistle.trie. +Require ethereum.tangerine_whistle.utils.message. +Require ethereum.tangerine_whistle.vm.interpreter. + +Definition apply_fork (old : BlockChain) : M BlockChain := + (* + 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 ` for + an example. + + Parameters + ---------- + old : + Previous block chain object. + + Returns + ------- + new : `BlockChain` + Upgraded block chain object for this hard fork. + *) + (* TODO statement *) + M.pure tt. + +Definition get_last_256_block_hashes (chain : BlockChain) : M (* TODO type *) := + (* + 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. + *) + do* M.assign "recent_blocks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "most_recent_block_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + M.get_field ~(| (* TODO expression *), "header" |) + |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "recent_block_hashes" |), "append" |) ~(| + M.get_local ~(| "most_recent_block_hash" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_transition (chain : BlockChain) (block : Block) : M unit := + (* + 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`. + *) + do* M.assign "parent_header" [[ + M.get_field ~(| (* TODO expression *), "header" |) in + ]] in + do* [[ M.get_local ~(| "validate_header" |) ~(| + M.get_field ~(| block, "header" |), + M.get_local ~(| "parent_header" |) + |) ]] in + do* [[ M.get_local ~(| "validate_ommers" |) ~(| + M.get_field ~(| block, "ommers" |), + M.get_field ~(| block, "header" |), + chain + |) ]] in + do* M.assign "apply_body_output" [[ + M.get_local ~(| "apply_body" |) ~(| + M.get_field ~(| chain, "state" |), + M.get_local ~(| "get_last_256_block_hashes" |) ~(| + chain + |), + M.get_field ~(| M.get_field ~(| block, "header" |), "coinbase" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "number" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "gas_limit" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "timestamp" |), + M.get_field ~(| M.get_field ~(| block, "header" |), "difficulty" |), + M.get_field ~(| block, "transactions" |), + M.get_field ~(| block, "ommers" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_field ~(| chain, "blocks" |), "append" |) ~(| + block + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_header (header : Header) (parent_header : Header) : M unit := + (* + 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 + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "block_difficulty" [[ + M.get_local ~(| "calculate_block_difficulty" |) ~(| + M.get_field ~(| header, "number" |), + M.get_field ~(| header, "timestamp" |), + M.get_field ~(| parent_header, "timestamp" |), + M.get_field ~(| parent_header, "difficulty" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "block_parent_hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + parent_header + |) + |) in + ]] in + (* TODO statement *) + do* [[ M.get_local ~(| "validate_proof_of_work" |) ~(| + header + |) ]] in + M.pure tt. + +Definition generate_header_hash_for_pow (header : Header) : M Hash32 := + (* + 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. + *) + do* M.assign "header_data_without_pow_artefacts" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_proof_of_work (header : Header) : M unit := + (* + 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. + *) + do* M.assign "header_hash" [[ + M.get_local ~(| "generate_header_hash_for_pow" |) ~(| + header + |) in + ]] in + do* M.assign "cache" [[ + ethereum.ethash.generate_cache ~(| + M.get_field ~(| header, "number" |) + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + do* M.assign "limit" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition check_transaction (tx : Transaction) (gas_available : Uint) : M 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. + *) + (* TODO statement *) + do* M.assign "sender_address" [[ + M.get_local ~(| "recover_sender" |) ~(| + tx + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition make_receipt (tx : Transaction) (post_state : Bytes32) (cumulative_gas_used : Uint) (logs : (* TODO type *)) : M 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. + *) + do* M.assign "receipt" [[ + blocks.Receipt ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition apply_body (state : State) (block_hashes : (* TODO type *)) (coinbase : Address) (block_number : Uint) (block_gas_limit : Uint) (block_time : U256) (block_difficulty : Uint) (transactions : (* TODO type *)) (ommers : (* TODO type *)) : M ApplyBodyOutput := + (* + 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 + ------- + apply_body_output : `ApplyBodyOutput` + Output of applying the block body to the state. + *) + do* M.assign "gas_available" [[ + block_gas_limit in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "pay_rewards" |) ~(| + state, + block_number, + coinbase, + ommers + |) ]] in + do* M.assign "block_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "block_logs_bloom" [[ + bloom.logs_bloom ~(| + M.get_local ~(| "block_logs" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition validate_ommers (ommers : (* TODO type *)) (block_header : Header) (chain : BlockChain) : M unit := + (* + 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. + *) + do* M.assign "block_hash" [[ + M.get_field ~(| __init__.rlp, "rlp_hash" |) ~(| + block_header + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "ommers_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "recent_canonical_blocks" [[ + (* TODO expression *) in + ]] in + do* M.assign "recent_canonical_block_hashes" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition pay_rewards (state : State) (block_number : Uint) (coinbase : Address) (ommers : (* TODO type *)) : M unit := + (* + 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. + *) + do* M.assign "ommer_count" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + ommers + |) + |) in + ]] in + do* M.assign "miner_reward" [[ + (* TODO expression *) in + ]] in + do* [[ state.create_ether ~(| + state, + coinbase, + M.get_local ~(| "miner_reward" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_transaction (env : (* TODO type *)) (tx : Transaction) : M (* TODO type *) := + (* + 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.blocks.Log, ...]` + Logs generated during execution. + *) + (* TODO statement *) + do* M.assign "sender" [[ + M.get_field ~(| env, "origin" |) in + ]] in + do* M.assign "sender_account" [[ + state.get_account ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) in + ]] in + do* M.assign "gas_fee" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "gas" [[ + (* TODO expression *) in + ]] in + do* [[ state.increment_nonce ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |) + |) ]] in + do* M.assign "sender_balance_after_gas_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "sender_balance_after_gas_fee" |) + |) + |) ]] in + do* M.assign "message" [[ + utils.message.prepare_message ~(| + M.get_local ~(| "sender" |), + M.get_field ~(| tx, "to" |), + M.get_field ~(| tx, "value" |), + M.get_field ~(| tx, "data" |), + M.get_local ~(| "gas" |), + env + |) in + ]] in + do* M.assign "output" [[ + vm.interpreter.process_message_call ~(| + M.get_local ~(| "message" |), + env + |) in + ]] in + do* M.assign "gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "gas_refund" [[ + M.get_local ~(| "min" |) ~(| + (* TODO expression *), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| M.get_local ~(| "output" |), "refund_counter" |) + |) + |) in + ]] in + do* M.assign "gas_refund_amount" [[ + (* TODO expression *) in + ]] in + do* M.assign "transaction_fee" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_used" [[ + (* TODO expression *) in + ]] in + do* M.assign "sender_balance_after_refund" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_local ~(| "sender" |), + M.get_local ~(| "sender_balance_after_refund" |) + |) ]] in + do* M.assign "coinbase_balance_after_mining_fee" [[ + (* TODO expression *) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| env, "coinbase" |), + M.get_local ~(| "coinbase_balance_after_mining_fee" |) + |) ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition validate_transaction (tx : Transaction) : M bool := + (* + 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 `_. + 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. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_intrinsic_cost (tx : Transaction) : M Uint := + (* + 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. + *) + do* M.assign "data_cost" [[ + 0 in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition recover_sender (tx : Transaction) : M Address := + (* + 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. + *) + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "public_key" [[ + ethereum.crypto.elliptic_curve.secp256k1_recover ~(| + M.get_local ~(| "r" |), + M.get_local ~(| "s" |), + (* TODO expression *), + M.get_local ~(| "signing_hash" |) ~(| + tx + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition signing_hash (tx : Transaction) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_header_hash (header : Header) : M Hash32 := + (* + 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. + *) + (* TODO statement *) + M.pure tt. + +Definition check_gas_limit (gas_limit : Uint) (parent_gas_limit : Uint) : M bool := + (* + 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. + *) + do* M.assign "max_adjustment_delta" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_block_difficulty (block_number : Uint) (block_timestamp : U256) (parent_timestamp : U256) (parent_difficulty : Uint) : M Uint := + (* + 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. + *) + do* M.assign "offset" [[ + (* TODO expression *) in + ]] in + do* M.assign "difficulty" [[ + (* TODO expression *) in + ]] in + do* M.assign "num_bomb_periods" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/fork_types.ast b/coq/ethereum/tangerine_whistle/fork_types.ast new file mode 100644 index 0000000000..acd2fbb7f5 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/fork_types.ast @@ -0,0 +1,146 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Types\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nTypes re-used throughout the specification, which are specific to Ethereum.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=2), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Bloom', ctx=Store())], + value=Name(id='Bytes256', ctx=Load())), + ClassDef( + name='Account', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n State associated with an address.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='balance', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='EMPTY_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Account', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[]))])), + FunctionDef( + name='encode_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='raw_account_data', + annotation=Name(id='Account', ctx=Load())), + arg( + arg='storage_root', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encode `Account` dataclass.\n\n Storage is not stored in the `Account` dataclass, so `Accounts` cannot be\n encoded without providing a storage root.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='nonce', + ctx=Load()), + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='balance', + ctx=Load()), + Name(id='storage_root', ctx=Load()), + Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Attribute( + value=Name(id='raw_account_data', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/fork_types.v b/coq/ethereum/tangerine_whistle/fork_types.v new file mode 100644 index 0000000000..d84cffdf45 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/fork_types.v @@ -0,0 +1,31 @@ +(* Generated *) +(* +Ethereum Types +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Types re-used throughout the specification, which are specific to Ethereum. +*) + +Require dataclasses. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.__init__. +Require ethereum.crypto.hash. + +Definition encode_account (raw_account_data : Account) (storage_root : Bytes) : M Bytes := + (* + Encode `Account` dataclass. + + Storage is not stored in the `Account` dataclass, so `Accounts` cannot be + encoded without providing a storage root. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/state.ast b/coq/ethereum/tangerine_whistle/state.ast new file mode 100644 index 0000000000..dce2e294a9 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/state.ast @@ -0,0 +1,1292 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState\n^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state contains all information that is preserved between transactions.\n\nIt consists of a main account trie and storage tries for each contract.\n\nThere is a distinction between an account that does not exist and\n`EMPTY_ACCOUNT`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='modify')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='EMPTY_ACCOUNT'), + alias(name='Account'), + alias(name='Address'), + alias(name='Root')], + level=1), + ImportFrom( + module='trie', + names=[ + alias(name='EMPTY_TRIE_ROOT'), + alias(name='Trie'), + alias(name='copy_trie'), + alias(name='root'), + alias(name='trie_get'), + alias(name='trie_set')], + level=1), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Contains all information that is preserved between transactions.\n ')), + AnnAssign( + target=Name(id='_main_trie', ctx=Store()), + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Constant(value=None))])))]), + simple=1), + AnnAssign( + target=Name(id='_storage_tries', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1), + AnnAssign( + target=Name(id='_snapshots', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='list', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Free resources held by the state. Used by optimized implementations to\n release file descriptors.\n ')), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Del())])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a state transaction.\n\n Transactions are entirely implicit and can be nested. It is not possible to\n calculate the state root during a transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='copy_trie', ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit a state transaction.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback a state transaction, resetting the state to the point when the\n corresponding `start_transaction()` call was made.\n\n Parameters\n ----------\n state : State\n The state.\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there\n is no account at the address.\n\n Use `get_account_optional()` if you care about the difference between a\n non-existent account and `EMPTY_ACCOUNT`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='account', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='account', ctx=Load()))], + orelse=[ + Return( + value=Name(id='EMPTY_ACCOUNT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Account', ctx=Load())), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the `Account` object at an address. Returns `None` (rather than\n `EMPTY_ACCOUNT`) if there is no account at the address.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to lookup.\n\n Returns\n -------\n account : `Account`\n Account at address.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=Name(id='account', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set the `Account` object at an address. Setting to `None` deletes\n the account (but not its storage, see `destroy_account()`).\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address to set.\n account : `Account`\n Account to set at address.\n ')), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the account at `address` and all of its storage.\n\n This function is made available exclusively for the `SELFDESTRUCT`\n opcode. It is expected that `SELFDESTRUCT` will be disabled in a future\n hardfork and this function will be removed.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account to destroy.\n ')), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Constant(value=None)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Completely remove the storage at `address`.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of account whose storage is to be deleted.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a value at a storage key on an account. Returns `U256(0)` if the\n storage key has not been set previously.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to lookup.\n\n Returns\n -------\n value : `U256`\n Value at the key.\n ')), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Return( + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Set a value at a storage key on an account. Setting to `U256(0)` deletes\n the key.\n\n Parameters\n ----------\n state: `State`\n The state\n address : `Address`\n Address of the account.\n key : `Bytes`\n Key to set.\n value : `U256`\n Value to set at the key.\n ')), + Assert( + test=Compare( + left=Call( + func=Name(id='trie_get', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='trie', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='trie', ctx=Store())], + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=True)), + keyword( + arg='default', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='trie', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='trie_set', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Dict(keys=[], values=[])]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Del())])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the storage root of an account.\n\n Parameters\n ----------\n state:\n The state\n address :\n Address of the account.\n\n Returns\n -------\n root : `Root`\n Storage root of the account.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Name(id='EMPTY_TRIE_ROOT', ctx=Load()))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculate the state root.\n\n Parameters\n ----------\n state:\n The current state.\n\n Returns\n -------\n root : `Root`\n The state root.\n ')), + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='_snapshots', + ctx=Load()))), + FunctionDef( + name='get_storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='storage_root', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + Return( + value=Call( + func=Name(id='root', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[ + keyword( + arg='get_storage_root', + value=Name(id='get_storage_root', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='account_exists', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account exists in the state trie\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n account_exists : `bool`\n True if account exists in the state trie, False otherwise\n ')), + Return( + value=Compare( + left=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='account_has_code_or_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if an account has non zero nonce or non empty code\n\n Parameters\n ----------\n state:\n The state\n address:\n Address of the account that needs to be checked.\n\n Returns\n -------\n has_code_or_nonce : `bool`\n True if if an account has non zero nonce or non empty code,\n False otherwise.\n ')), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=b'')])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='modify_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='f', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Account', ctx=Load())], + ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modify an `Account` in the `State`.\n ')), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='modify', ctx=Load()), + args=[ + Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + Name(id='f', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='move_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='sender_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='recipient_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Move funds between accounts.\n ')), + FunctionDef( + name='reduce_sender_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increase_recipient_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='recipient', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='recipient', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='sender_address', ctx=Load()), + Name(id='reduce_sender_balance', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='recipient_address', ctx=Load()), + Name(id='increase_recipient_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_account_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets the balance of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n\n amount:\n The amount that needs to set in balance.\n ')), + FunctionDef( + name='set_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store())], + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='set_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='touch_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes an account to state.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n The address of the account that need to initialised.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='EMPTY_ACCOUNT', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='increment_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Increments the nonce of an account.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose nonce needs to be incremented.\n ')), + FunctionDef( + name='increase_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_nonce', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='set_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sets Account code.\n\n Parameters\n ----------\n state:\n The current state.\n\n address:\n Address of the account whose code needs to be update.\n\n code:\n The bytecode that needs to be set.\n ')), + FunctionDef( + name='write_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sender', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='sender', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='write_code', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='create_ether', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add newly created ether to an account.\n\n Parameters\n ----------\n state:\n The current state.\n address:\n Address of the account to which ether is added.\n amount:\n The amount of ether to be added to the account of interest.\n ')), + FunctionDef( + name='increase_balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='account', + annotation=Name(id='Account', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Store()), + op=Add(), + value=Name(id='amount', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + Expr( + value=Call( + func=Name(id='modify_state', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='increase_balance', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/state.v b/coq/ethereum/tangerine_whistle/state.v new file mode 100644 index 0000000000..7e913e3666 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/state.v @@ -0,0 +1,484 @@ +(* Generated *) +(* +State +^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state contains all information that is preserved between transactions. + +It consists of a main account trie and storage tries for each contract. + +There is a distinction between an account that does not exist and +`EMPTY_ACCOUNT`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.tangerine_whistle.fork_types. +Require ethereum.tangerine_whistle.trie. + +Definition close_state (state : State) : M unit := + (* + Free resources held by the state. Used by optimized implementations to + release file descriptors. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition begin_transaction (state : State) : M unit := + (* + Start a state transaction. + + Transactions are entirely implicit and can be nested. It is not possible to + calculate the state root during a transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "append" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition commit_transaction (state : State) : M unit := + (* + Commit a state transaction. + + Parameters + ---------- + state : State + The state. + *) + do* [[ M.get_field ~(| M.get_field ~(| state, "_snapshots" |), "pop" |) ~(| + + |) ]] in + M.pure tt. + +Definition rollback_transaction (state : State) : M unit := + (* + Rollback a state transaction, resetting the state to the point when the + corresponding `start_transaction()` call was made. + + Parameters + ---------- + state : State + The state. + *) + (* TODO assignment *) + M.pure tt. + +Definition get_account (state : State) (address : Address) : M Account := + (* + Get the `Account` object at an address. Returns `EMPTY_ACCOUNT` if there + is no account at the address. + + Use `get_account_optional()` if you care about the difference between a + non-existent account and `EMPTY_ACCOUNT`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account_optional" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_account_optional (state : State) (address : Address) : M (* TODO type *) := + (* + Get the `Account` object at an address. Returns `None` (rather than + `EMPTY_ACCOUNT`) if there is no account at the address. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to lookup. + + Returns + ------- + account : `Account` + Account at address. + *) + do* M.assign "account" [[ + trie.trie_get ~(| + M.get_field ~(| state, "_main_trie" |), + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition set_account (state : State) (address : Address) (account : (* TODO type *)) : M unit := + (* + Set the `Account` object at an address. Setting to `None` deletes + the account (but not its storage, see `destroy_account()`). + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address to set. + account : `Account` + Account to set at address. + *) + do* [[ trie.trie_set ~(| + M.get_field ~(| state, "_main_trie" |), + address, + account + |) ]] in + M.pure tt. + +Definition destroy_account (state : State) (address : Address) : M unit := + (* + Completely remove the account at `address` and all of its storage. + + This function is made available exclusively for the `SELFDESTRUCT` + opcode. It is expected that `SELFDESTRUCT` will be disabled in a future + hardfork and this function will be removed. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account to destroy. + *) + do* [[ M.get_local ~(| "destroy_storage" |) ~(| + state, + address + |) ]] in + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + tt + |) ]] in + M.pure tt. + +Definition destroy_storage (state : State) (address : Address) : M unit := + (* + Completely remove the storage at `address`. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of account whose storage is to be deleted. + *) + (* TODO statement *) + M.pure tt. + +Definition get_storage (state : State) (address : Address) (key : Bytes) : M U256 := + (* + Get a value at a storage key on an account. Returns `U256(0)` if the + storage key has not been set previously. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to lookup. + + Returns + ------- + value : `U256` + Value at the key. + *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* M.assign "value" [[ + trie.trie_get ~(| + M.get_local ~(| "trie" |), + key + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition set_storage (state : State) (address : Address) (key : Bytes) (value : U256) : M unit := + (* + Set a value at a storage key on an account. Setting to `U256(0)` deletes + the key. + + Parameters + ---------- + state: `State` + The state + address : `Address` + Address of the account. + key : `Bytes` + Key to set. + value : `U256` + Value to set at the key. + *) + (* TODO statement *) + do* M.assign "trie" [[ + M.get_field ~(| M.get_field ~(| state, "_storage_tries" |), "get" |) ~(| + address + |) in + ]] in + (* TODO statement *) + do* [[ trie.trie_set ~(| + M.get_local ~(| "trie" |), + key, + value + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition storage_root (state : State) (address : Address) : M Root := + (* + Calculate the storage root of an account. + + Parameters + ---------- + state: + The state + address : + Address of the account. + + Returns + ------- + root : `Root` + Storage root of the account. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition state_root (state : State) : M Root := + (* + Calculate the state root. + + Parameters + ---------- + state: + The current state. + + Returns + ------- + root : `Root` + The state root. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition account_exists (state : State) (address : Address) : M bool := + (* + Checks if an account exists in the state trie + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + account_exists : `bool` + True if account exists in the state trie, False otherwise + *) + (* TODO statement *) + M.pure tt. + +Definition account_has_code_or_nonce (state : State) (address : Address) : M bool := + (* + Checks if an account has non zero nonce or non empty code + + Parameters + ---------- + state: + The state + address: + Address of the account that needs to be checked. + + Returns + ------- + has_code_or_nonce : `bool` + True if if an account has non zero nonce or non empty code, + False otherwise. + *) + do* M.assign "account" [[ + M.get_local ~(| "get_account" |) ~(| + state, + address + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition modify_state (state : State) (address : Address) (f : (* TODO type *)) : M unit := + (* + Modify an `Account` in the `State`. + *) + do* [[ M.get_local ~(| "set_account" |) ~(| + state, + address, + ethereum_types.frozen.modify ~(| + M.get_local ~(| "get_account" |) ~(| + state, + address + |), + f + |) + |) ]] in + M.pure tt. + +Definition move_ether (state : State) (sender_address : Address) (recipient_address : Address) (amount : U256) : M unit := + (* + Move funds between accounts. + *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + sender_address, + M.get_local ~(| "reduce_sender_balance" |) + |) ]] in + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + recipient_address, + M.get_local ~(| "increase_recipient_balance" |) + |) ]] in + M.pure tt. + +Definition set_account_balance (state : State) (address : Address) (amount : U256) : M unit := + (* + Sets the balance of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + + amount: + The amount that needs to set in balance. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "set_balance" |) + |) ]] in + M.pure tt. + +Definition touch_account (state : State) (address : Address) : M unit := + (* + Initializes an account to state. + + Parameters + ---------- + state: + The current state. + + address: + The address of the account that need to initialised. + *) + (* TODO statement *) + M.pure tt. + +Definition increment_nonce (state : State) (address : Address) : M unit := + (* + Increments the nonce of an account. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose nonce needs to be incremented. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_nonce" |) + |) ]] in + M.pure tt. + +Definition set_code (state : State) (address : Address) (code : Bytes) : M unit := + (* + Sets Account code. + + Parameters + ---------- + state: + The current state. + + address: + Address of the account whose code needs to be update. + + code: + The bytecode that needs to be set. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "write_code" |) + |) ]] in + M.pure tt. + +Definition create_ether (state : State) (address : Address) (amount : U256) : M unit := + (* + Add newly created ether to an account. + + Parameters + ---------- + state: + The current state. + address: + Address of the account to which ether is added. + amount: + The amount of ether to be added to the account of interest. + *) + (* TODO statement *) + do* [[ M.get_local ~(| "modify_state" |) ~(| + state, + address, + M.get_local ~(| "increase_balance" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/transactions.ast b/coq/ethereum/tangerine_whistle/transactions.ast new file mode 100644 index 0000000000..19d5c9707f --- /dev/null +++ b/coq/ethereum/tangerine_whistle/transactions.ast @@ -0,0 +1,106 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTransactions are atomic units of work created externally to Ethereum and\nsubmitted to be executed. If Ethereum is viewed as a state machine,\ntransactions are the events that move between states.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=1), + Assign( + targets=[ + Name(id='TX_BASE_COST', ctx=Store())], + value=Constant(value=21000)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_NON_ZERO', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='TX_DATA_COST_PER_ZERO', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='TX_CREATE_COST', ctx=Store())], + value=Constant(value=32000)), + ClassDef( + name='Transaction', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Atomic operation performed on the block chain.\n ')), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='to', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='v', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='r', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='s', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/transactions.v b/coq/ethereum/tangerine_whistle/transactions.v new file mode 100644 index 0000000000..2545cb2dd1 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/transactions.v @@ -0,0 +1,13 @@ +(* Generated *) +(* +Transactions are atomic units of work created externally to Ethereum and +submitted to be executed. If Ethereum is viewed as a state machine, +transactions are the events that move between states. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.frozen. +Require ethereum_types.numeric. +Require ethereum.tangerine_whistle.fork_types. diff --git a/coq/ethereum/tangerine_whistle/trie.ast b/coq/ethereum/tangerine_whistle/trie.ast new file mode 100644 index 0000000000..74fe020daf --- /dev/null +++ b/coq/ethereum/tangerine_whistle/trie.ast @@ -0,0 +1,1618 @@ +Module( + body=[ + Expr( + value=Constant(value='\nState Trie\n^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe state trie is the structure responsible for storing\n`.fork_types.Account` objects.\n')), + Import( + names=[ + alias(name='copy')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass'), + alias(name='field')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict'), + alias(name='Generic'), + alias(name='List'), + alias(name='Mapping'), + alias(name='MutableMapping'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.frozen', + names=[ + alias(name='slotted_freezable')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.dao_fork', + names=[ + alias(name='trie', asname='previous_trie')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=2), + ImportFrom( + module='blocks', + names=[ + alias(name='Receipt')], + level=1), + ImportFrom( + module='fork_types', + names=[ + alias(name='Account'), + alias(name='Address'), + alias(name='Root'), + alias(name='encode_account')], + level=1), + ImportFrom( + module='transactions', + names=[ + alias(name='Transaction')], + level=1), + Assign( + targets=[ + Name(id='EMPTY_TRIE_ROOT', ctx=Store())], + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Constant(value='56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Node', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Bytes', ctx=Load()), + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load()), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + Assign( + targets=[ + Name(id='K', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='K')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Bytes', ctx=Load()))])), + Assign( + targets=[ + Name(id='V', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='V'), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()), + Name(id='Bytes', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Transaction', ctx=Load()), + ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Receipt', ctx=Load()), + ctx=Load()), + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + ClassDef( + name='LeafNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Leaf node in the Merkle Trie')), + AnnAssign( + target=Name(id='rest_of_key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='ExtensionNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Extension node in the Merkle Trie')), + AnnAssign( + target=Name(id='key_segment', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='subnode', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='BranchNode', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Branch node in the Merkle Trie')), + AnnAssign( + target=Name(id='subnodes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='slotted_freezable', ctx=Load()), + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='InternalNode', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='LeafNode', ctx=Load()), + Name(id='ExtensionNode', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='encode_internal_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Encodes a Merkle Trie node into its RLP form. The RLP will then be\n serialized into a `Bytes` and hashed unless it is less that 32 bytes\n when serialized.\n\n This function also accepts `None`, representing the absence of a node,\n which is encoded to `b""`.\n\n Parameters\n ----------\n node : Optional[InternalNode]\n The node to encode.\n\n Returns\n -------\n encoded : `rlp.Extended`\n The node encoded as RLP.\n ')), + AnnAssign( + target=Name(id='unencoded', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + If( + test=Compare( + left=Name(id='node', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='LeafNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='rest_of_key', + ctx=Load()), + Constant(value=True)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ExtensionNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Name(id='nibble_list_to_compact', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='key_segment', + ctx=Load()), + Constant(value=False)], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='subnode', + ctx=Load())], + ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BranchNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='unencoded', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='node', ctx=Load()), + attr='subnodes', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='value', + ctx=Load())], + ctx=Load())))], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Invalid internal node type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value='!')])], + keywords=[]))])])])]), + Assign( + targets=[ + Name(id='encoded', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='unencoded', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Name(id='unencoded', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='encoded', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load())), + FunctionDef( + name='encode_node', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='node', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Encode a Node for storage in the Merkle Trie.\n\n Currently mostly an unimplemented stub.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Return( + value=Call( + func=Name(id='encode_account', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='Transaction', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Name(id='node', ctx=Load()))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='previous_trie', ctx=Load()), + attr='encode_node', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='storage_root', ctx=Load())], + keywords=[]))])])])], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + ClassDef( + name='Trie', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The Merkle Trie.\n ')), + AnnAssign( + target=Name(id='secured', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='default', ctx=Store()), + annotation=Name(id='V', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='field', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='default_factory', + value=Name(id='dict', ctx=Load()))]), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a copy of `trie`. Since only frozen objects may be stored in tries,\n the contents are reused.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to copy.\n\n Returns\n -------\n new_trie : `Trie[K, V]`\n A copy of the trie.\n ')), + Return( + value=Call( + func=Name(id='Trie', ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='copy', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load())), + arg( + arg='value', + annotation=Name(id='V', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores an item in a Merkle Trie.\n\n This method deletes the key if `value == trie.default`, because the Merkle\n Trie represents the default value by omitting it from the trie.\n\n Parameters\n ----------\n trie: `Trie`\n Trie to store in.\n key : `Bytes`\n Key to lookup.\n value : `V`\n Node to insert at `key`.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())]), + body=[ + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Del())])], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='trie_get', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='key', + annotation=Name(id='K', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Gets an item from the Merkle Trie.\n\n This method returns `trie.default` if the key is missing.\n\n Parameters\n ----------\n trie:\n Trie to lookup in.\n key :\n Key to lookup.\n\n Returns\n -------\n node : `V`\n Node at `key` in the trie.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Attribute( + value=Name(id='trie', ctx=Load()), + attr='default', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='V', ctx=Load())), + FunctionDef( + name='common_prefix_length', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='a', + annotation=Name(id='Sequence', ctx=Load())), + arg( + arg='b', + annotation=Name(id='Sequence', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find the longest common prefix of two sequences.\n ')), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='i', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='b', ctx=Load())], + keywords=[])]), + Compare( + left=Subscript( + value=Name(id='a', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Subscript( + value=Name(id='b', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Name(id='i', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='a', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='nibble_list_to_compact', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='x', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='is_leaf', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compresses nibble-list into a standard byte array with a flag.\n\n A nibble-list is a list of byte values no greater than `15`. The flag is\n encoded in high nibble of the highest byte. The flag nibble can be broken\n down into two two-bit flags.\n\n Highest nibble::\n\n +---+---+----------+--------+\n | _ | _ | is_leaf | parity |\n +---+---+----------+--------+\n 3 2 1 0\n\n\n The lowest bit of the nibble encodes the parity of the length of the\n remaining nibbles -- `0` when even and `1` when odd. The second lowest bit\n is used to distinguish leaf and extension nodes. The other two bits are not\n used.\n\n Parameters\n ----------\n x :\n Array of nibbles.\n is_leaf :\n True if this is part of a leaf node, or false if it is an extension\n node.\n\n Returns\n -------\n compressed : `bytearray`\n Compact byte array.\n ')), + Assign( + targets=[ + Name(id='compact', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=BinOp( + left=BinOp( + left=Constant(value=2), + op=Mult(), + right=Name(id='is_leaf', ctx=Load())), + op=Add(), + right=Constant(value=1))), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + keywords=[])), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=1), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + Constant(value=2)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='compact', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=16), + op=Mult(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=Name(id='i', ctx=Load()), + ctx=Load())), + op=Add(), + right=Subscript( + value=Name(id='x', ctx=Load()), + slice=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + keywords=[]))], + orelse=[])]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='compact', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='bytes_to_nibble_list', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='bytes_', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16).\n\n Parameters\n ----------\n bytes_:\n The `Bytes` to convert.\n\n Returns\n -------\n nibble_list : `Bytes`\n The `Bytes` in nibble-list format.\n ')), + Assign( + targets=[ + Name(id='nibble_list', ctx=Store())], + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=Constant(value=2), + op=Mult(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='byte_index', ctx=Store()), + Name(id='byte', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='bytes_', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=240)), + op=RShift(), + right=Constant(value=4))), + Assign( + targets=[ + Subscript( + value=Name(id='nibble_list', ctx=Load()), + slice=BinOp( + left=BinOp( + left=Name(id='byte_index', ctx=Load()), + op=Mult(), + right=Constant(value=2)), + op=Add(), + right=Constant(value=1)), + ctx=Store())], + value=BinOp( + left=Name(id='byte', ctx=Load()), + op=BitAnd(), + right=Constant(value=15)))], + orelse=[]), + Return( + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Name(id='nibble_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='_prepare_trie', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Prepares the trie for root calculation. Removes values that are empty,\n hashes the keys (if `secured == True`) and encodes all the nodes.\n\n Parameters\n ----------\n trie :\n The `Trie` to prepare.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n Returns\n -------\n out : `Mapping[ethereum.base_types.Bytes, Node]`\n Object with keys mapped to nibble-byte form.\n ')), + AnnAssign( + target=Name(id='mapped', ctx=Store()), + annotation=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='preimage', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='trie', ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='Account', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Name(id='get_storage_root', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Call( + func=Name(id='get_storage_root', ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='encoded_value', ctx=Store())], + value=Call( + func=Name(id='encode_node', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))]), + If( + test=Compare( + left=Name(id='encoded_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=b'')]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='trie', ctx=Load()), + attr='secured', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='preimage', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Name(id='preimage', ctx=Load()))]), + Assign( + targets=[ + Subscript( + value=Name(id='mapped', ctx=Load()), + slice=Call( + func=Name(id='bytes_to_nibble_list', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ctx=Store())], + value=Name(id='encoded_value', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='mapped', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trie', + annotation=Subscript( + value=Name(id='Trie', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='K', ctx=Load()), + Name(id='V', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='get_storage_root', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='Address', ctx=Load())], + ctx=Load()), + Name(id='Root', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Computes the root of a modified merkle patricia trie (MPT).\n\n Parameters\n ----------\n trie :\n `Trie` to get the root of.\n get_storage_root :\n Function to get the storage root of an account. Needed to encode\n `Account` objects.\n\n\n Returns\n -------\n root : `.fork_types.Root`\n MPT root of the underlying key-value pairs.\n ')), + Assign( + targets=[ + Name(id='obj', ctx=Store())], + value=Call( + func=Name(id='_prepare_trie', ctx=Load()), + args=[ + Name(id='trie', ctx=Load()), + Name(id='get_storage_root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='root_node', ctx=Store())], + value=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]), + ops=[ + Lt()], + comparators=[ + Constant(value=32)]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Name(id='root_node', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='patricialize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='obj', + annotation=Subscript( + value=Name(id='Mapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='level', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Structural composition function.\n\n Used to recursively patricialize and merkleize a dictionary. Includes\n memoization of the tree structure and hashes.\n\n Parameters\n ----------\n obj :\n Underlying trie key-value pairs, with keys in nibble-list format.\n level :\n Current trie level.\n\n Returns\n -------\n node : `ethereum.base_types.Bytes`\n Root node of `obj`.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=None))], + orelse=[]), + Assign( + targets=[ + Name(id='arbitrary_key', ctx=Store())], + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Call( + func=Name(id='iter', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='leaf', ctx=Store())], + value=Call( + func=Name(id='LeafNode', ctx=Load()), + args=[ + Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load()), + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='arbitrary_key', ctx=Load()), + ctx=Load())], + keywords=[])), + Return( + value=Name(id='leaf', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='substring', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())), + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='substring', ctx=Load())], + keywords=[])), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='prefix_length', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load()), + Call( + func=Name(id='common_prefix_length', ctx=Load()), + args=[ + Name(id='substring', ctx=Load()), + Subscript( + value=Name(id='key', ctx=Load()), + slice=Slice( + lower=Name(id='level', ctx=Load())), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Break()], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='prefix_length', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='prefix', ctx=Store())], + value=Subscript( + value=Name(id='arbitrary_key', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='level', ctx=Load())], + keywords=[]), + op=Add(), + right=Name(id='prefix_length', ctx=Load()))), + ctx=Load())), + Return( + value=Call( + func=Name(id='ExtensionNode', ctx=Load()), + args=[ + Name(id='prefix', ctx=Load()), + Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='prefix_length', ctx=Load())], + keywords=[]))], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='branches', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='MutableMapping', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='Bytes', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='branches', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict(keys=[], values=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='key', ctx=Store()), + iter=Name(id='obj', ctx=Load()), + body=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Name(id='level', ctx=Load())]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()), + Tuple( + elts=[ + Name(id='Account', ctx=Load()), + Name(id='Receipt', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + Raise( + exc=Name(id='AssertionError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='branches', ctx=Load()), + slice=Subscript( + value=Name(id='key', ctx=Load()), + slice=Name(id='level', ctx=Load()), + ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='obj', ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))])], + orelse=[]), + Return( + value=Call( + func=Name(id='BranchNode', ctx=Load()), + args=[ + ListComp( + elt=Call( + func=Name(id='encode_internal_node', ctx=Load()), + args=[ + Call( + func=Name(id='patricialize', ctx=Load()), + args=[ + Subscript( + value=Name(id='branches', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Load()), + BinOp( + left=Name(id='level', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[]), + generators=[ + comprehension( + target=Name(id='k', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=16)], + keywords=[]), + ifs=[], + is_async=0)]), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='InternalNode', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/trie.v b/coq/ethereum/tangerine_whistle/trie.v new file mode 100644 index 0000000000..3b45315972 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/trie.v @@ -0,0 +1,293 @@ +(* Generated *) +(* +State Trie +^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The state trie is the structure responsible for storing +`.fork_types.Account` objects. +*) + + +Definition encode_internal_node (node : (* TODO type *)) : M (* TODO type *) := + (* + Encodes a Merkle Trie node into its RLP form. The RLP will then be + serialized into a `Bytes` and hashed unless it is less that 32 bytes + when serialized. + + This function also accepts `None`, representing the absence of a node, + which is encoded to `b""`. + + Parameters + ---------- + node : Optional[InternalNode] + The node to encode. + + Returns + ------- + encoded : `rlp.Extended` + The node encoded as RLP. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "encoded" [[ + M.get_field ~(| M.get_local ~(| "rlp" |), "encode" |) ~(| + M.get_local ~(| "unencoded" |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition encode_node (node : Node) (storage_root : (* TODO type *)) : M Bytes := + (* + Encode a Node for storage in the Merkle Trie. + + Currently mostly an unimplemented stub. + *) + (* TODO statement *) + M.pure tt. + +Definition copy_trie (trie : (* TODO type *)) : M (* TODO type *) := + (* + Create a copy of `trie`. Since only frozen objects may be stored in tries, + the contents are reused. + + Parameters + ---------- + trie: `Trie` + Trie to copy. + + Returns + ------- + new_trie : `Trie[K, V]` + A copy of the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_set (trie : (* TODO type *)) (key : K) (value : V) : M unit := + (* + Stores an item in a Merkle Trie. + + This method deletes the key if `value == trie.default`, because the Merkle + Trie represents the default value by omitting it from the trie. + + Parameters + ---------- + trie: `Trie` + Trie to store in. + key : `Bytes` + Key to lookup. + value : `V` + Node to insert at `key`. + *) + (* TODO statement *) + M.pure tt. + +Definition trie_get (trie : (* TODO type *)) (key : K) : M V := + (* + Gets an item from the Merkle Trie. + + This method returns `trie.default` if the key is missing. + + Parameters + ---------- + trie: + Trie to lookup in. + key : + Key to lookup. + + Returns + ------- + node : `V` + Node at `key` in the trie. + *) + (* TODO statement *) + M.pure tt. + +Definition common_prefix_length (a : Sequence) (b : Sequence) : M int := + (* + Find the longest common prefix of two sequences. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition nibble_list_to_compact (x : Bytes) (is_leaf : bool) : M Bytes := + (* + Compresses nibble-list into a standard byte array with a flag. + + A nibble-list is a list of byte values no greater than `15`. The flag is + encoded in high nibble of the highest byte. The flag nibble can be broken + down into two two-bit flags. + + Highest nibble:: + + +---+---+----------+--------+ + | _ | _ | is_leaf | parity | + +---+---+----------+--------+ + 3 2 1 0 + + + The lowest bit of the nibble encodes the parity of the length of the + remaining nibbles -- `0` when even and `1` when odd. The second lowest bit + is used to distinguish leaf and extension nodes. The other two bits are not + used. + + Parameters + ---------- + x : + Array of nibbles. + is_leaf : + True if this is part of a leaf node, or false if it is an extension + node. + + Returns + ------- + compressed : `bytearray` + Compact byte array. + *) + do* M.assign "compact" [[ + M.get_local ~(| "bytearray" |) ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition bytes_to_nibble_list (bytes_ : Bytes) : M Bytes := + (* + Converts a `Bytes` into to a sequence of nibbles (bytes with value < 16). + + Parameters + ---------- + bytes_: + The `Bytes` to convert. + + Returns + ------- + nibble_list : `Bytes` + The `Bytes` in nibble-list format. + *) + do* M.assign "nibble_list" [[ + M.get_local ~(| "bytearray" |) ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition _prepare_trie (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M (* TODO type *) := + (* + Prepares the trie for root calculation. Removes values that are empty, + hashes the keys (if `secured == True`) and encodes all the nodes. + + Parameters + ---------- + trie : + The `Trie` to prepare. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + Returns + ------- + out : `Mapping[ethereum.base_types.Bytes, Node]` + Object with keys mapped to nibble-byte form. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition root (trie : (* TODO type *)) (get_storage_root : (* TODO type *)) : M Root := + (* + Computes the root of a modified merkle patricia trie (MPT). + + Parameters + ---------- + trie : + `Trie` to get the root of. + get_storage_root : + Function to get the storage root of an account. Needed to encode + `Account` objects. + + + Returns + ------- + root : `.fork_types.Root` + MPT root of the underlying key-value pairs. + *) + do* M.assign "obj" [[ + M.get_local ~(| "_prepare_trie" |) ~(| + trie, + get_storage_root + |) in + ]] in + do* M.assign "root_node" [[ + M.get_local ~(| "encode_internal_node" |) ~(| + M.get_local ~(| "patricialize" |) ~(| + M.get_local ~(| "obj" |), + M.get_local ~(| "Uint" |) ~(| + 0 + |) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition patricialize (obj : (* TODO type *)) (level : Uint) : M (* TODO type *) := + (* + Structural composition function. + + Used to recursively patricialize and merkleize a dictionary. Includes + memoization of the tree structure and hashes. + + Parameters + ---------- + obj : + Underlying trie key-value pairs, with keys in nibble-list format. + level : + Current trie level. + + Returns + ------- + node : `ethereum.base_types.Bytes` + Root node of `obj`. + *) + (* TODO statement *) + do* M.assign "arbitrary_key" [[ + M.get_local ~(| "next" |) ~(| + M.get_local ~(| "iter" |) ~(| + obj + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "substring" [[ + (* TODO expression *) in + ]] in + do* M.assign "prefix_length" [[ + M.get_local ~(| "len" |) ~(| + M.get_local ~(| "substring" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "value" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/utils/__init__.ast b/coq/ethereum/tangerine_whistle/utils/__init__.ast new file mode 100644 index 0000000000..abf907c15b --- /dev/null +++ b/coq/ethereum/tangerine_whistle/utils/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions unique to this particular fork.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/utils/__init__.v b/coq/ethereum/tangerine_whistle/utils/__init__.v new file mode 100644 index 0000000000..7f30fe939b --- /dev/null +++ b/coq/ethereum/tangerine_whistle/utils/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Utility functions unique to this particular fork. +*) + diff --git a/coq/ethereum/tangerine_whistle/utils/address.ast b/coq/ethereum/tangerine_whistle/utils/address.ast new file mode 100644 index 0000000000..e675f900b1 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/utils/address.ast @@ -0,0 +1,139 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddress specific functions used in this tangerine whistle version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + names=[ + alias(name='rlp')], + level=3), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + FunctionDef( + name='to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert a Uint or U256 value to a valid address (20 bytes).\n\n Parameters\n ----------\n data :\n The string to be converted to bytes.\n\n Returns\n -------\n address : `Address`\n The obtained address.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Subscript( + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[]), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load())), + FunctionDef( + name='compute_contract_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='nonce', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Computes address of the new account that needs to be created.\n\n Parameters\n ----------\n address :\n The address of the account that wants to create the new account.\n nonce :\n The transaction count of the account that wants to create the new\n account.\n\n Returns\n -------\n address: `ethereum.tangerine_whistle.fork_types.Address`\n The computed address of the new account.\n ')), + Assign( + targets=[ + Name(id='computed_address', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List( + elts=[ + Name(id='address', ctx=Load()), + Name(id='nonce', ctx=Load())], + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='canonical_address', ctx=Store())], + value=Subscript( + value=Name(id='computed_address', ctx=Load()), + slice=Slice( + lower=UnaryOp( + op=USub(), + operand=Constant(value=20))), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='canonical_address', ctx=Load()), + Constant(value=20)], + keywords=[])), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Name(id='padded_address', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/utils/address.v b/coq/ethereum/tangerine_whistle/utils/address.v new file mode 100644 index 0000000000..ec6712c185 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/utils/address.v @@ -0,0 +1,75 @@ +(* Generated *) +(* +Hardfork Utility Functions For Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Address specific functions used in this tangerine whistle version of +specification. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.__init__. +Require ethereum.tangerine_whistle.fork_types. + +Definition to_address (data : (* TODO type *)) : M Address := + (* + Convert a Uint or U256 value to a valid address (20 bytes). + + Parameters + ---------- + data : + The string to be converted to bytes. + + Returns + ------- + address : `Address` + The obtained address. + *) + (* TODO statement *) + M.pure tt. + +Definition compute_contract_address (address : Address) (nonce : Uint) : M Address := + (* + Computes address of the new account that needs to be created. + + Parameters + ---------- + address : + The address of the account that wants to create the new account. + nonce : + The transaction count of the account that wants to create the new + account. + + Returns + ------- + address: `ethereum.tangerine_whistle.fork_types.Address` + The computed address of the new account. + *) + do* M.assign "computed_address" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_field ~(| __init__.rlp, "encode" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "canonical_address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "canonical_address" |), + 20 + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/utils/hexadecimal.ast b/coq/ethereum/tangerine_whistle/utils/hexadecimal.ast new file mode 100644 index 0000000000..eecf2fddd8 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/utils/hexadecimal.ast @@ -0,0 +1,124 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal utility functions used in this specification, specific to\nTangerine Whistle types.\n')), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='remove_hex_prefix')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address'), + alias(name='Bloom'), + alias(name='Root')], + level=2), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to trie root.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to trie root.\n\n Returns\n -------\n root : `Root`\n Trie root obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Root', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='hex_to_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bloom.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bloom.\n\n Returns\n -------\n bloom : `Bloom`\n Bloom obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bloom', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bloom', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Address (20 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Address.\n\n Returns\n -------\n address : `Address`\n The address obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Address', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=40), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Address', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/utils/hexadecimal.v b/coq/ethereum/tangerine_whistle/utils/hexadecimal.v new file mode 100644 index 0000000000..ba90513cd1 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/utils/hexadecimal.v @@ -0,0 +1,69 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal utility functions used in this specification, specific to +Tangerine Whistle types. +*) + +Require ethereum.utils.hexadecimal. +Require ethereum.tangerine_whistle.fork_types. + +Definition hex_to_root (hex_string : str) : M Root := + (* + Convert hex string to trie root. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to trie root. + + Returns + ------- + root : `Root` + Trie root obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bloom (hex_string : str) : M Bloom := + (* + Convert hex string to bloom. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bloom. + + Returns + ------- + bloom : `Bloom` + Bloom obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_address (hex_string : str) : M Address := + (* + Convert hex string to Address (20 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Address. + + Returns + ------- + address : `Address` + The address obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/utils/message.ast b/coq/ethereum/tangerine_whistle/utils/message.ast new file mode 100644 index 0000000000..2ce306d939 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/utils/message.ast @@ -0,0 +1,234 @@ +Module( + body=[ + Expr( + value=Constant(value='\nHardfork Utility Functions For The Message Data-structure\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMessage specific functions used in this tangerine whistle version of\nspecification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Environment'), + alias(name='Message')], + level=2), + ImportFrom( + module='address', + names=[ + alias(name='compute_contract_address')], + level=1), + FunctionDef( + name='prepare_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='target', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='data', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load())), + arg( + arg='code_address', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=True)]), + body=[ + Expr( + value=Constant(value='\n Execute a transaction against the provided environment.\n\n Parameters\n ----------\n caller :\n Address which initiated the transaction\n target :\n Address whose code will be executed\n value :\n Value to be transferred.\n data :\n Array of bytes provided to the code in `target`.\n gas :\n Gas provided for the code in `target`.\n env :\n Environment for the Ethereum Virtual Machine.\n code_address :\n This is usually same as the `target` address except when an alternative\n accounts code needs to be executed.\n eg. `CALLCODE` calling a precompile.\n should_transfer_value :\n if True ETH should be transferred while executing a message call.\n\n Returns\n -------\n message: `ethereum.tangerine_whistle.vm.Message`\n Items containing contract creation or message call specific data.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Bytes0', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Name(id='caller', ctx=Load()), + BinOp( + left=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='caller', ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Name(id='data', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='target', ctx=Load()), + Name(id='Address', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_target', ctx=Store())], + value=Name(id='target', ctx=Load())), + Assign( + targets=[ + Name(id='msg_data', ctx=Store())], + value=Name(id='data', ctx=Load())), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Name(id='target', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + If( + test=Compare( + left=Name(id='code_address', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Name(id='target', ctx=Load()))], + orelse=[])], + orelse=[ + Raise( + exc=Call( + func=Name(id='AssertionError', ctx=Load()), + args=[ + Constant(value='Target must be address or empty bytes')], + keywords=[]))])]), + Return( + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='target', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='msg_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Name(id='current_target', ctx=Load())), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='parent_evm', + value=Constant(value=None))]))], + decorator_list=[], + returns=Name(id='Message', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/utils/message.v b/coq/ethereum/tangerine_whistle/utils/message.v new file mode 100644 index 0000000000..1e447e6a61 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/utils/message.v @@ -0,0 +1,57 @@ +(* Generated *) +(* +Hardfork Utility Functions For The Message Data-structure +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Message specific functions used in this tangerine whistle version of +specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.tangerine_whistle.fork_types. +Require ethereum.tangerine_whistle.state. +Require ethereum.tangerine_whistle.vm. +Require ethereum.tangerine_whistle.utils.address. + +Definition prepare_message (caller : Address) (target : (* TODO type *)) (value : U256) (data : Bytes) (gas : Uint) (env : Environment) (code_address : (* TODO type *)) (should_transfer_value : bool) : M Message := + (* + Execute a transaction against the provided environment. + + Parameters + ---------- + caller : + Address which initiated the transaction + target : + Address whose code will be executed + value : + Value to be transferred. + data : + Array of bytes provided to the code in `target`. + gas : + Gas provided for the code in `target`. + env : + Environment for the Ethereum Virtual Machine. + code_address : + This is usually same as the `target` address except when an alternative + accounts code needs to be executed. + eg. `CALLCODE` calling a precompile. + should_transfer_value : + if True ETH should be transferred while executing a message call. + + Returns + ------- + message: `ethereum.tangerine_whistle.vm.Message` + Items containing contract creation or message call specific data. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/__init__.ast b/coq/ethereum/tangerine_whistle/vm/__init__.ast new file mode 100644 index 0000000000..b679ec6d01 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/__init__.ast @@ -0,0 +1,362 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThe abstract computer which runs the code stored in an\n`.fork_types.Account`.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='State')], + level=2), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='Environment'), + Constant(value='Evm'), + Constant(value='Message')], + ctx=Load())), + ClassDef( + name='Environment', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items external to the virtual machine itself, provided by the environment.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='origin', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_price', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='time', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='State', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='dict', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Message', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Items that are used by contract creation or message call.\n ')), + AnnAssign( + target=Name(id='caller', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='target', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes0', ctx=Load()), + Name(id='Address', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='current_target', ctx=Store()), + annotation=Name(id='Address', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='value', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code_address', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='should_transfer_value', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Evm', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The internal state of the virtual machine.')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='valid_jump_destinations', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='incorporate_child_on_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of a successful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='logs', + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='incorporate_child_on_error', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='child_evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Incorporate the state of an unsuccessful `child_evm` into the parent `evm`.\n\n Parameters\n ----------\n evm :\n The parent `EVM`.\n child_evm :\n The child evm to incorporate.\n ')), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='gas_left', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/__init__.v b/coq/ethereum/tangerine_whistle/vm/__init__.v new file mode 100644 index 0000000000..39d1dc8d15 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/__init__.v @@ -0,0 +1,65 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +The abstract computer which runs the code stored in an +`.fork_types.Account`. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.tangerine_whistle.blocks. +Require ethereum.tangerine_whistle.fork_types. +Require ethereum.tangerine_whistle.state. + +Definition incorporate_child_on_success (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of a successful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "logs" |) ]] [[ + M.get_field ~(| child_evm, "logs" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "refund_counter" |) ]] [[ + M.get_field ~(| child_evm, "refund_counter" |) + ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "update" |) ~(| + M.get_field ~(| child_evm, "accounts_to_delete" |) + |) ]] in + M.pure tt. + +Definition incorporate_child_on_error (evm : Evm) (child_evm : Evm) : M unit := + (* + Incorporate the state of an unsuccessful `child_evm` into the parent `evm`. + + Parameters + ---------- + evm : + The parent `EVM`. + child_evm : + The child evm to incorporate. + *) + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_field ~(| child_evm, "gas_left" |) + ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/exceptions.ast b/coq/ethereum/tangerine_whistle/vm/exceptions.ast new file mode 100644 index 0000000000..3194c3c232 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/exceptions.ast @@ -0,0 +1,125 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Exceptions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nExceptions which cause the EVM to halt exceptionally.\n')), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException')], + level=0), + ClassDef( + name='ExceptionalHalt', + bases=[ + Name(id='EthereumException', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Indicates that the EVM has experienced an exceptional halt. This causes\n execution to immediately end with all gas being consumed.\n '))], + decorator_list=[]), + ClassDef( + name='StackUnderflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a pop is executed on an empty stack.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='StackOverflowError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when a push is executed on a stack at max capacity.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='OutOfGasError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Occurs when an operation costs more than the amount of gas left in the\n frame.\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='InvalidOpcode', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when an invalid opcode is encountered.\n ')), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='InvalidJumpDestError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Occurs when the destination of a jump operation doesn't meet any of the\n following criteria:\n\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n "))], + decorator_list=[]), + ClassDef( + name='StackDepthLimitError', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the message depth is greater than `1024`\n ')), + Pass()], + decorator_list=[]), + ClassDef( + name='AddressCollision', + bases=[ + Name(id='ExceptionalHalt', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Raised when the new contract address has a collision.\n ')), + Pass()], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/exceptions.v b/coq/ethereum/tangerine_whistle/vm/exceptions.v new file mode 100644 index 0000000000..47e26555d5 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/exceptions.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Exceptions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Exceptions which cause the EVM to halt exceptionally. +*) + +Require ethereum.exceptions. diff --git a/coq/ethereum/tangerine_whistle/vm/gas.ast b/coq/ethereum/tangerine_whistle/vm/gas.ast new file mode 100644 index 0000000000..2b211e47e5 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/gas.ast @@ -0,0 +1,801 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Gas\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM gas constants and calculators.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='GasAndRefund'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='OutOfGasError')], + level=1), + Assign( + targets=[ + Name(id='GAS_JUMPDEST', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BASE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_VERY_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SLOAD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_SET', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_UPDATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOW', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MID', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_HIGH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=10)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_MEMORY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_KECCAK256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=6)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_COPY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BLOCK_HASH', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_EXTERNAL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_BALANCE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=400)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_DATA', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_LOG_TOPIC', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=375)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CREATE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CODE_DEPOSIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_ZERO', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=700)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_VALUE', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=9000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_CALL_STIPEND', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2300)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=5000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=25000)], + keywords=[])), + Assign( + targets=[ + Name(id='REFUND_SELF_DESTRUCT', ctx=Store())], + value=Constant(value=24000)), + Assign( + targets=[ + Name(id='GAS_ECRECOVER', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3000)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=60)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_SHA256_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=600)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_RIPEMD160_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=120)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=15)], + keywords=[])), + Assign( + targets=[ + Name(id='GAS_IDENTITY_WORD', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=3)], + keywords=[])), + ClassDef( + name='ExtendMemory', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the parameters for memory extension in opcodes\n\n `cost`: `ethereum.base_types.Uint`\n The gas required to perform the extension\n `expand_by`: `ethereum.base_types.Uint`\n The size by which the memory will be extended\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='expand_by', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='MessageCallGas', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Define the gas cost and stipend for executing the call opcodes.\n\n `cost`: `ethereum.base_types.Uint`\n The non-refundable portion of gas reserved for executing the\n call opcode.\n `stipend`: `ethereum.base_types.Uint`\n The portion of gas available to sub-calls that is refundable\n if not consumed\n ')), + AnnAssign( + target=Name(id='cost', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stipend', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='charge_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='amount', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts `amount` from `evm.gas_left`.\n\n Parameters\n ----------\n evm :\n The current EVM.\n amount :\n The amount of gas the current operation requires.\n\n ')), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='GasAndRefund', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='amount', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='amount', ctx=Load())]), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))], + orelse=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='amount', ctx=Load()))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calculate_memory_gas_cost', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='size_in_bytes', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas cost for allocating memory\n to the smallest multiple of 32 bytes,\n such that the allocated size is at least as big as the given size.\n\n Parameters\n ----------\n size_in_bytes :\n The size of the data in bytes.\n\n Returns\n -------\n total_gas_cost : `ethereum.base_types.Uint`\n The gas cost for storing data in memory.\n ')), + Assign( + targets=[ + Name(id='size_in_words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='size_in_bytes', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='linear_cost', ctx=Store())], + value=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Mult(), + right=Name(id='GAS_MEMORY', ctx=Load()))), + Assign( + targets=[ + Name(id='quadratic_cost', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='size_in_words', ctx=Load()), + op=Pow(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=512)], + keywords=[]))), + Assign( + targets=[ + Name(id='total_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='linear_cost', ctx=Load()), + op=Add(), + right=Name(id='quadratic_cost', ctx=Load()))), + Try( + body=[ + Return( + value=Name(id='total_gas_cost', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Name(id='OutOfGasError', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='calculate_gas_extend_memory', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='extensions', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the gas amount to extend memory\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n extensions:\n List of extensions to be made to the memory.\n Consists of a tuple of start position and size.\n\n Returns\n -------\n extend_memory: `ExtendMemory`\n ')), + Assign( + targets=[ + Name(id='size_to_extend', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='to_be_paid', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='memory', ctx=Load())], + keywords=[])], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='start_position', ctx=Store()), + Name(id='size', ctx=Store())], + ctx=Store()), + iter=Name(id='extensions', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='size', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='before_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Name(id='current_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after_size', ctx=Store())], + value=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))], + keywords=[])), + If( + test=Compare( + left=Name(id='after_size', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='before_size', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AugAssign( + target=Name(id='size_to_extend', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='after_size', ctx=Load()), + op=Sub(), + right=Name(id='before_size', ctx=Load()))), + Assign( + targets=[ + Name(id='already_paid', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='before_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='total_cost', ctx=Store())], + value=Call( + func=Name(id='calculate_memory_gas_cost', ctx=Load()), + args=[ + Name(id='after_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='to_be_paid', ctx=Store()), + op=Add(), + value=BinOp( + left=Name(id='total_cost', ctx=Load()), + op=Sub(), + right=Name(id='already_paid', ctx=Load()))), + Assign( + targets=[ + Name(id='current_size', ctx=Store())], + value=Name(id='after_size', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='ExtendMemory', ctx=Load()), + args=[ + Name(id='to_be_paid', ctx=Load()), + Name(id='size_to_extend', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='ExtendMemory', ctx=Load())), + FunctionDef( + name='calculate_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='gas_left', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='memory_cost', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='extra_gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='call_stipend', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Name(id='GAS_CALL_STIPEND', ctx=Load())]), + body=[ + Expr( + value=Constant(value='\n Calculates the MessageCallGas (cost and stipend) for\n executing call Opcodes.\n\n Parameters\n ----------\n value:\n The amount of `ETH` that needs to be transferred.\n gas :\n The amount of gas provided to the message-call.\n gas_left :\n The amount of gas left in the current frame.\n memory_cost :\n The amount needed to extend the memory in the current frame.\n extra_gas :\n The amount of gas needed for transferring value + creating a new\n account inside a message call.\n call_stipend :\n The amount of stipend provided to a message call to execute code while\n transferring value(ETH).\n\n Returns\n -------\n message_call_gas: `MessageCallGas`\n ')), + Assign( + targets=[ + Name(id='call_stipend', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='call_stipend', ctx=Load()))), + If( + test=Compare( + left=Name(id='gas_left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + BinOp( + left=Name(id='extra_gas', ctx=Load()), + op=Add(), + right=Name(id='memory_cost', ctx=Load()))]), + body=[ + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='gas', ctx=Load()), + Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='gas_left', ctx=Load()), + op=Sub(), + right=Name(id='memory_cost', ctx=Load())), + op=Sub(), + right=Name(id='extra_gas', ctx=Load()))], + keywords=[])], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallGas', ctx=Load()), + args=[ + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='extra_gas', ctx=Load())), + BinOp( + left=Name(id='gas', ctx=Load()), + op=Add(), + right=Name(id='call_stipend', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='MessageCallGas', ctx=Load())), + FunctionDef( + name='max_message_call_gas', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Calculates the maximum gas that is allowed for making a message call\n\n Parameters\n ----------\n gas :\n The amount of gas provided to the message-call.\n\n Returns\n -------\n max_allowed_message_call_gas: `ethereum.base_types.Uint`\n The maximum gas allowed for making the message-call.\n ')), + Return( + value=BinOp( + left=Name(id='gas', ctx=Load()), + op=Sub(), + right=BinOp( + left=Name(id='gas', ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]))))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/gas.v b/coq/ethereum/tangerine_whistle/vm/gas.v new file mode 100644 index 0000000000..4708b4166b --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/gas.v @@ -0,0 +1,171 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Gas +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM gas constants and calculators. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.utils.numeric. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.exceptions. + +Definition charge_gas (evm : Evm) (amount : Uint) : M unit := + (* + Subtracts `amount` from `evm.gas_left`. + + Parameters + ---------- + evm : + The current EVM. + amount : + The amount of gas the current operation requires. + + *) + do* [[ ethereum.trace.evm_trace ~(| + evm, + ethereum.trace.GasAndRefund ~(| + M.get_local ~(| "int" |) ~(| + amount + |) + |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_memory_gas_cost (size_in_bytes : Uint) : M Uint := + (* + Calculates the gas cost for allocating memory + to the smallest multiple of 32 bytes, + such that the allocated size is at least as big as the given size. + + Parameters + ---------- + size_in_bytes : + The size of the data in bytes. + + Returns + ------- + total_gas_cost : `ethereum.base_types.Uint` + The gas cost for storing data in memory. + *) + do* M.assign "size_in_words" [[ + (* TODO expression *) in + ]] in + do* M.assign "linear_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "quadratic_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "total_gas_cost" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition calculate_gas_extend_memory (memory : bytearray) (extensions : (* TODO type *)) : M ExtendMemory := + (* + Calculates the gas amount to extend memory + + Parameters + ---------- + memory : + Memory contents of the EVM. + extensions: + List of extensions to be made to the memory. + Consists of a tuple of start position and size. + + Returns + ------- + extend_memory: `ExtendMemory` + *) + do* M.assign "size_to_extend" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "to_be_paid" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "current_size" [[ + ethereum_types.numeric.Uint ~(| + M.get_local ~(| "len" |) ~(| + memory + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition calculate_message_call_gas (value : U256) (gas : Uint) (gas_left : Uint) (memory_cost : Uint) (extra_gas : Uint) (call_stipend : Uint) : M MessageCallGas := + (* + Calculates the MessageCallGas (cost and stipend) for + executing call Opcodes. + + Parameters + ---------- + value: + The amount of `ETH` that needs to be transferred. + gas : + The amount of gas provided to the message-call. + gas_left : + The amount of gas left in the current frame. + memory_cost : + The amount needed to extend the memory in the current frame. + extra_gas : + The amount of gas needed for transferring value + creating a new + account inside a message call. + call_stipend : + The amount of stipend provided to a message call to execute code while + transferring value(ETH). + + Returns + ------- + message_call_gas: `MessageCallGas` + *) + do* M.assign "call_stipend" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "gas" [[ + M.get_local ~(| "min" |) ~(| + gas, + M.get_local ~(| "max_message_call_gas" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition max_message_call_gas (gas : Uint) : M Uint := + (* + Calculates the maximum gas that is allowed for making a message call + + Parameters + ---------- + gas : + The amount of gas provided to the message-call. + + Returns + ------- + max_allowed_message_call_gas: `ethereum.base_types.Uint` + The maximum gas allowed for making the message-call. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/__init__.ast b/coq/ethereum/tangerine_whistle/vm/instructions/__init__.ast new file mode 100644 index 0000000000..0931c390c8 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/__init__.ast @@ -0,0 +1,1648 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEVM Instruction Encoding (Opcodes)\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMachine readable representations of EVM instructions, and a mapping to their\nimplementations.\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + names=[ + alias(name='arithmetic', asname='arithmetic_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='bitwise', asname='bitwise_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='block', asname='block_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='comparison', asname='comparison_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='control_flow', asname='control_flow_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='environment', asname='environment_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='keccak', asname='keccak_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='log', asname='log_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='memory', asname='memory_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='stack', asname='stack_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='storage', asname='storage_instructions')], + level=1), + ImportFrom( + names=[ + alias(name='system', asname='system_instructions')], + level=1), + ClassDef( + name='Ops', + bases=[ + Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enum for EVM Opcodes\n ')), + Assign( + targets=[ + Name(id='ADD', ctx=Store())], + value=Constant(value=1)), + Assign( + targets=[ + Name(id='MUL', ctx=Store())], + value=Constant(value=2)), + Assign( + targets=[ + Name(id='SUB', ctx=Store())], + value=Constant(value=3)), + Assign( + targets=[ + Name(id='DIV', ctx=Store())], + value=Constant(value=4)), + Assign( + targets=[ + Name(id='SDIV', ctx=Store())], + value=Constant(value=5)), + Assign( + targets=[ + Name(id='MOD', ctx=Store())], + value=Constant(value=6)), + Assign( + targets=[ + Name(id='SMOD', ctx=Store())], + value=Constant(value=7)), + Assign( + targets=[ + Name(id='ADDMOD', ctx=Store())], + value=Constant(value=8)), + Assign( + targets=[ + Name(id='MULMOD', ctx=Store())], + value=Constant(value=9)), + Assign( + targets=[ + Name(id='EXP', ctx=Store())], + value=Constant(value=10)), + Assign( + targets=[ + Name(id='SIGNEXTEND', ctx=Store())], + value=Constant(value=11)), + Assign( + targets=[ + Name(id='LT', ctx=Store())], + value=Constant(value=16)), + Assign( + targets=[ + Name(id='GT', ctx=Store())], + value=Constant(value=17)), + Assign( + targets=[ + Name(id='SLT', ctx=Store())], + value=Constant(value=18)), + Assign( + targets=[ + Name(id='SGT', ctx=Store())], + value=Constant(value=19)), + Assign( + targets=[ + Name(id='EQ', ctx=Store())], + value=Constant(value=20)), + Assign( + targets=[ + Name(id='ISZERO', ctx=Store())], + value=Constant(value=21)), + Assign( + targets=[ + Name(id='AND', ctx=Store())], + value=Constant(value=22)), + Assign( + targets=[ + Name(id='OR', ctx=Store())], + value=Constant(value=23)), + Assign( + targets=[ + Name(id='XOR', ctx=Store())], + value=Constant(value=24)), + Assign( + targets=[ + Name(id='NOT', ctx=Store())], + value=Constant(value=25)), + Assign( + targets=[ + Name(id='BYTE', ctx=Store())], + value=Constant(value=26)), + Assign( + targets=[ + Name(id='KECCAK', ctx=Store())], + value=Constant(value=32)), + Assign( + targets=[ + Name(id='ADDRESS', ctx=Store())], + value=Constant(value=48)), + Assign( + targets=[ + Name(id='BALANCE', ctx=Store())], + value=Constant(value=49)), + Assign( + targets=[ + Name(id='ORIGIN', ctx=Store())], + value=Constant(value=50)), + Assign( + targets=[ + Name(id='CALLER', ctx=Store())], + value=Constant(value=51)), + Assign( + targets=[ + Name(id='CALLVALUE', ctx=Store())], + value=Constant(value=52)), + Assign( + targets=[ + Name(id='CALLDATALOAD', ctx=Store())], + value=Constant(value=53)), + Assign( + targets=[ + Name(id='CALLDATASIZE', ctx=Store())], + value=Constant(value=54)), + Assign( + targets=[ + Name(id='CALLDATACOPY', ctx=Store())], + value=Constant(value=55)), + Assign( + targets=[ + Name(id='CODESIZE', ctx=Store())], + value=Constant(value=56)), + Assign( + targets=[ + Name(id='CODECOPY', ctx=Store())], + value=Constant(value=57)), + Assign( + targets=[ + Name(id='GASPRICE', ctx=Store())], + value=Constant(value=58)), + Assign( + targets=[ + Name(id='EXTCODESIZE', ctx=Store())], + value=Constant(value=59)), + Assign( + targets=[ + Name(id='EXTCODECOPY', ctx=Store())], + value=Constant(value=60)), + Assign( + targets=[ + Name(id='BLOCKHASH', ctx=Store())], + value=Constant(value=64)), + Assign( + targets=[ + Name(id='COINBASE', ctx=Store())], + value=Constant(value=65)), + Assign( + targets=[ + Name(id='TIMESTAMP', ctx=Store())], + value=Constant(value=66)), + Assign( + targets=[ + Name(id='NUMBER', ctx=Store())], + value=Constant(value=67)), + Assign( + targets=[ + Name(id='DIFFICULTY', ctx=Store())], + value=Constant(value=68)), + Assign( + targets=[ + Name(id='GASLIMIT', ctx=Store())], + value=Constant(value=69)), + Assign( + targets=[ + Name(id='STOP', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='JUMP', ctx=Store())], + value=Constant(value=86)), + Assign( + targets=[ + Name(id='JUMPI', ctx=Store())], + value=Constant(value=87)), + Assign( + targets=[ + Name(id='PC', ctx=Store())], + value=Constant(value=88)), + Assign( + targets=[ + Name(id='GAS', ctx=Store())], + value=Constant(value=90)), + Assign( + targets=[ + Name(id='JUMPDEST', ctx=Store())], + value=Constant(value=91)), + Assign( + targets=[ + Name(id='SLOAD', ctx=Store())], + value=Constant(value=84)), + Assign( + targets=[ + Name(id='SSTORE', ctx=Store())], + value=Constant(value=85)), + Assign( + targets=[ + Name(id='POP', ctx=Store())], + value=Constant(value=80)), + Assign( + targets=[ + Name(id='PUSH1', ctx=Store())], + value=Constant(value=96)), + Assign( + targets=[ + Name(id='PUSH2', ctx=Store())], + value=Constant(value=97)), + Assign( + targets=[ + Name(id='PUSH3', ctx=Store())], + value=Constant(value=98)), + Assign( + targets=[ + Name(id='PUSH4', ctx=Store())], + value=Constant(value=99)), + Assign( + targets=[ + Name(id='PUSH5', ctx=Store())], + value=Constant(value=100)), + Assign( + targets=[ + Name(id='PUSH6', ctx=Store())], + value=Constant(value=101)), + Assign( + targets=[ + Name(id='PUSH7', ctx=Store())], + value=Constant(value=102)), + Assign( + targets=[ + Name(id='PUSH8', ctx=Store())], + value=Constant(value=103)), + Assign( + targets=[ + Name(id='PUSH9', ctx=Store())], + value=Constant(value=104)), + Assign( + targets=[ + Name(id='PUSH10', ctx=Store())], + value=Constant(value=105)), + Assign( + targets=[ + Name(id='PUSH11', ctx=Store())], + value=Constant(value=106)), + Assign( + targets=[ + Name(id='PUSH12', ctx=Store())], + value=Constant(value=107)), + Assign( + targets=[ + Name(id='PUSH13', ctx=Store())], + value=Constant(value=108)), + Assign( + targets=[ + Name(id='PUSH14', ctx=Store())], + value=Constant(value=109)), + Assign( + targets=[ + Name(id='PUSH15', ctx=Store())], + value=Constant(value=110)), + Assign( + targets=[ + Name(id='PUSH16', ctx=Store())], + value=Constant(value=111)), + Assign( + targets=[ + Name(id='PUSH17', ctx=Store())], + value=Constant(value=112)), + Assign( + targets=[ + Name(id='PUSH18', ctx=Store())], + value=Constant(value=113)), + Assign( + targets=[ + Name(id='PUSH19', ctx=Store())], + value=Constant(value=114)), + Assign( + targets=[ + Name(id='PUSH20', ctx=Store())], + value=Constant(value=115)), + Assign( + targets=[ + Name(id='PUSH21', ctx=Store())], + value=Constant(value=116)), + Assign( + targets=[ + Name(id='PUSH22', ctx=Store())], + value=Constant(value=117)), + Assign( + targets=[ + Name(id='PUSH23', ctx=Store())], + value=Constant(value=118)), + Assign( + targets=[ + Name(id='PUSH24', ctx=Store())], + value=Constant(value=119)), + Assign( + targets=[ + Name(id='PUSH25', ctx=Store())], + value=Constant(value=120)), + Assign( + targets=[ + Name(id='PUSH26', ctx=Store())], + value=Constant(value=121)), + Assign( + targets=[ + Name(id='PUSH27', ctx=Store())], + value=Constant(value=122)), + Assign( + targets=[ + Name(id='PUSH28', ctx=Store())], + value=Constant(value=123)), + Assign( + targets=[ + Name(id='PUSH29', ctx=Store())], + value=Constant(value=124)), + Assign( + targets=[ + Name(id='PUSH30', ctx=Store())], + value=Constant(value=125)), + Assign( + targets=[ + Name(id='PUSH31', ctx=Store())], + value=Constant(value=126)), + Assign( + targets=[ + Name(id='PUSH32', ctx=Store())], + value=Constant(value=127)), + Assign( + targets=[ + Name(id='DUP1', ctx=Store())], + value=Constant(value=128)), + Assign( + targets=[ + Name(id='DUP2', ctx=Store())], + value=Constant(value=129)), + Assign( + targets=[ + Name(id='DUP3', ctx=Store())], + value=Constant(value=130)), + Assign( + targets=[ + Name(id='DUP4', ctx=Store())], + value=Constant(value=131)), + Assign( + targets=[ + Name(id='DUP5', ctx=Store())], + value=Constant(value=132)), + Assign( + targets=[ + Name(id='DUP6', ctx=Store())], + value=Constant(value=133)), + Assign( + targets=[ + Name(id='DUP7', ctx=Store())], + value=Constant(value=134)), + Assign( + targets=[ + Name(id='DUP8', ctx=Store())], + value=Constant(value=135)), + Assign( + targets=[ + Name(id='DUP9', ctx=Store())], + value=Constant(value=136)), + Assign( + targets=[ + Name(id='DUP10', ctx=Store())], + value=Constant(value=137)), + Assign( + targets=[ + Name(id='DUP11', ctx=Store())], + value=Constant(value=138)), + Assign( + targets=[ + Name(id='DUP12', ctx=Store())], + value=Constant(value=139)), + Assign( + targets=[ + Name(id='DUP13', ctx=Store())], + value=Constant(value=140)), + Assign( + targets=[ + Name(id='DUP14', ctx=Store())], + value=Constant(value=141)), + Assign( + targets=[ + Name(id='DUP15', ctx=Store())], + value=Constant(value=142)), + Assign( + targets=[ + Name(id='DUP16', ctx=Store())], + value=Constant(value=143)), + Assign( + targets=[ + Name(id='SWAP1', ctx=Store())], + value=Constant(value=144)), + Assign( + targets=[ + Name(id='SWAP2', ctx=Store())], + value=Constant(value=145)), + Assign( + targets=[ + Name(id='SWAP3', ctx=Store())], + value=Constant(value=146)), + Assign( + targets=[ + Name(id='SWAP4', ctx=Store())], + value=Constant(value=147)), + Assign( + targets=[ + Name(id='SWAP5', ctx=Store())], + value=Constant(value=148)), + Assign( + targets=[ + Name(id='SWAP6', ctx=Store())], + value=Constant(value=149)), + Assign( + targets=[ + Name(id='SWAP7', ctx=Store())], + value=Constant(value=150)), + Assign( + targets=[ + Name(id='SWAP8', ctx=Store())], + value=Constant(value=151)), + Assign( + targets=[ + Name(id='SWAP9', ctx=Store())], + value=Constant(value=152)), + Assign( + targets=[ + Name(id='SWAP10', ctx=Store())], + value=Constant(value=153)), + Assign( + targets=[ + Name(id='SWAP11', ctx=Store())], + value=Constant(value=154)), + Assign( + targets=[ + Name(id='SWAP12', ctx=Store())], + value=Constant(value=155)), + Assign( + targets=[ + Name(id='SWAP13', ctx=Store())], + value=Constant(value=156)), + Assign( + targets=[ + Name(id='SWAP14', ctx=Store())], + value=Constant(value=157)), + Assign( + targets=[ + Name(id='SWAP15', ctx=Store())], + value=Constant(value=158)), + Assign( + targets=[ + Name(id='SWAP16', ctx=Store())], + value=Constant(value=159)), + Assign( + targets=[ + Name(id='MLOAD', ctx=Store())], + value=Constant(value=81)), + Assign( + targets=[ + Name(id='MSTORE', ctx=Store())], + value=Constant(value=82)), + Assign( + targets=[ + Name(id='MSTORE8', ctx=Store())], + value=Constant(value=83)), + Assign( + targets=[ + Name(id='MSIZE', ctx=Store())], + value=Constant(value=89)), + Assign( + targets=[ + Name(id='LOG0', ctx=Store())], + value=Constant(value=160)), + Assign( + targets=[ + Name(id='LOG1', ctx=Store())], + value=Constant(value=161)), + Assign( + targets=[ + Name(id='LOG2', ctx=Store())], + value=Constant(value=162)), + Assign( + targets=[ + Name(id='LOG3', ctx=Store())], + value=Constant(value=163)), + Assign( + targets=[ + Name(id='LOG4', ctx=Store())], + value=Constant(value=164)), + Assign( + targets=[ + Name(id='CREATE', ctx=Store())], + value=Constant(value=240)), + Assign( + targets=[ + Name(id='CALL', ctx=Store())], + value=Constant(value=241)), + Assign( + targets=[ + Name(id='CALLCODE', ctx=Store())], + value=Constant(value=242)), + Assign( + targets=[ + Name(id='RETURN', ctx=Store())], + value=Constant(value=243)), + Assign( + targets=[ + Name(id='DELEGATECALL', ctx=Store())], + value=Constant(value=244)), + Assign( + targets=[ + Name(id='SELFDESTRUCT', ctx=Store())], + value=Constant(value=255))], + decorator_list=[]), + AnnAssign( + target=Name(id='op_implementation', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Ops', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MUL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SUB', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SDIV', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MULMOD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SIGNEXTEND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SGT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EQ', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ISZERO', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='AND', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='OR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='XOR', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NOT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BYTE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='KECCAK', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BLOCKHASH', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='COINBASE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='TIMESTAMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='NUMBER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DIFFICULTY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASLIMIT', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MLOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSTORE8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='MSIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ADDRESS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='BALANCE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='ORIGIN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLER', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLVALUE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATALOAD', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATASIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLDATACOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GASPRICE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODESIZE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='EXTCODECOPY', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SSTORE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPI', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PC', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='GAS', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='POP', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH17', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH18', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH19', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH20', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH21', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH22', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH23', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH24', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH25', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH26', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH27', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH28', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH29', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH30', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH31', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DUP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP5', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP6', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP7', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP8', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP9', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP10', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP11', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP12', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP13', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP14', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP15', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SWAP16', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG0', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG1', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG2', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG3', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='LOG4', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CREATE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='RETURN', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='CALLCODE', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='DELEGATECALL', + ctx=Load()), + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='SELFDESTRUCT', + ctx=Load())], + values=[ + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='stop', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='add', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mul', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sub', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='div', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='sdiv', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='smod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='addmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='mulmod', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='exp', + ctx=Load()), + Attribute( + value=Name(id='arithmetic_instructions', ctx=Load()), + attr='signextend', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_less_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='signed_greater_than', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='equal', + ctx=Load()), + Attribute( + value=Name(id='comparison_instructions', ctx=Load()), + attr='is_zero', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_and', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_or', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_xor', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='bitwise_not', + ctx=Load()), + Attribute( + value=Name(id='bitwise_instructions', ctx=Load()), + attr='get_byte', + ctx=Load()), + Attribute( + value=Name(id='keccak_instructions', ctx=Load()), + attr='keccak', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sload', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='block_hash', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='timestamp', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='number', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='difficulty', + ctx=Load()), + Attribute( + value=Name(id='block_instructions', ctx=Load()), + attr='gas_limit', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mload', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='mstore8', + ctx=Load()), + Attribute( + value=Name(id='memory_instructions', ctx=Load()), + attr='msize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='address', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='balance', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='origin', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='callvalue', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldataload', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatasize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='calldatacopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='codecopy', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='gasprice', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodesize', + ctx=Load()), + Attribute( + value=Name(id='environment_instructions', ctx=Load()), + attr='extcodecopy', + ctx=Load()), + Attribute( + value=Name(id='storage_instructions', ctx=Load()), + attr='sstore', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jump', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpi', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='pc', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='gas_left', + ctx=Load()), + Attribute( + value=Name(id='control_flow_instructions', ctx=Load()), + attr='jumpdest', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='pop', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push17', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push18', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push19', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push20', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push21', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push22', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push23', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push24', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push25', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push26', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push27', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push28', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push29', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push30', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push31', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='push32', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='dup16', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap1', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap2', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap3', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap4', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap5', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap6', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap7', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap8', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap9', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap10', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap11', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap12', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap13', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap14', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap15', + ctx=Load()), + Attribute( + value=Name(id='stack_instructions', ctx=Load()), + attr='swap16', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log0', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log1', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log2', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log3', + ctx=Load()), + Attribute( + value=Name(id='log_instructions', ctx=Load()), + attr='log4', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='create', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='return_', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='call', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='callcode', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='delegatecall', + ctx=Load()), + Attribute( + value=Name(id='system_instructions', ctx=Load()), + attr='selfdestruct', + ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/__init__.v b/coq/ethereum/tangerine_whistle/vm/instructions/__init__.v new file mode 100644 index 0000000000..cbd7e7e63a --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/__init__.v @@ -0,0 +1,16 @@ +(* Generated *) +(* +EVM Instruction Encoding (Opcodes) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Machine readable representations of EVM instructions, and a mapping to their +implementations. +*) + diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/arithmetic.ast b/coq/ethereum/tangerine_whistle/vm/instructions/arithmetic.ast new file mode 100644 index 0000000000..fac19904f0 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/arithmetic.ast @@ -0,0 +1,1289 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Arithmetic Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Arithmetic instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='get_sign')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_EXPONENTIATION'), + alias(name='GAS_EXPONENTIATION_PER_BYTE'), + alias(name='GAS_LOW'), + alias(name='GAS_MID'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the top two elements of the stack together, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_add', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sub', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Subtracts the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_sub', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mul', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiply the top two elements of the stack, and pushes the result back\n on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='wrapping_mul', + ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='div', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Integer division of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='dividend', ctx=Load()), + op=FloorDiv(), + right=Name(id='divisor', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='quotient', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='U255_CEIL_VALUE', ctx=Store())], + value=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=255))), + FunctionDef( + name='sdiv', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed integer division of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='dividend', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='divisor', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=Constant(value=0))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='dividend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load()))]), + Compare( + left=Name(id='divisor', ctx=Load()), + ops=[ + Eq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=1))])]), + body=[ + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=UnaryOp( + op=USub(), + operand=Name(id='U255_CEIL_VALUE', ctx=Load())))], + orelse=[ + Assign( + targets=[ + Name(id='sign', ctx=Store())], + value=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + BinOp( + left=Name(id='dividend', ctx=Load()), + op=Mult(), + right=Name(id='divisor', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='quotient', ctx=Store())], + value=BinOp( + left=Name(id='sign', ctx=Load()), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='dividend', ctx=Load())], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='divisor', ctx=Load())], + keywords=[]))))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='quotient', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo remainder of the top two elements of the stack. Pushes the result\n back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='x', ctx=Load()), + op=Mod(), + right=Name(id='y', ctx=Load())))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='remainder', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='smod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed modulo remainder of the top two elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='y', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=Constant(value=0))], + orelse=[ + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='get_sign', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mult(), + right=BinOp( + left=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='x', ctx=Load())], + keywords=[]), + op=Mod(), + right=Call( + func=Name(id='abs', ctx=Load()), + args=[ + Name(id='y', ctx=Load())], + keywords=[]))))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_signed', + ctx=Load()), + args=[ + Name(id='remainder', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='addmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo addition of the top 2 elements with the 3rd element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Add(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mulmod', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Modulo multiplication of the top 2 elements with the 3rd element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='z', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='z', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='x', ctx=Load()), + op=Mult(), + right=Name(id='y', ctx=Load())), + op=Mod(), + right=Name(id='z', ctx=Load()))], + keywords=[]))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='exp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Exponential operation of the top 2 elements. Pushes the result back on\n the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bits', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='exponent', ctx=Load()), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='exponent_bytes', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='exponent_bits', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=7)], + keywords=[])), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_EXPONENTIATION', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_EXPONENTIATION_PER_BYTE', ctx=Load()), + op=Mult(), + right=Name(id='exponent_bytes', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='pow', ctx=Load()), + args=[ + Name(id='base', ctx=Load()), + Name(id='exponent', ctx=Load()), + BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signextend', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign extend operation. In other words, extend a signed number which\n fits in N bytes to 32 bytes.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_num', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_num', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Call( + func=Name(id='bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value_bytes', ctx=Store())], + value=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Constant(value=31), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='byte_num', ctx=Load())], + keywords=[]))), + ctx=Load())), + Assign( + targets=[ + Name(id='sign_bit', ctx=Store())], + value=BinOp( + left=Subscript( + value=Name(id='value_bytes', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + op=RShift(), + right=Constant(value=7))), + If( + test=Compare( + left=Name(id='sign_bit', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value_bytes', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='num_bytes_prepend', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + op=Sub(), + right=BinOp( + left=Name(id='byte_num', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='bytearray', ctx=Load()), + args=[ + BinOp( + left=List( + elts=[ + Constant(value=255)], + ctx=Load()), + op=Mult(), + right=Name(id='num_bytes_prepend', ctx=Load()))], + keywords=[]), + op=Add(), + right=Name(id='value_bytes', ctx=Load()))], + keywords=[]))])]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/arithmetic.v b/coq/ethereum/tangerine_whistle/vm/instructions/arithmetic.v new file mode 100644 index 0000000000..52e6b6b24e --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/arithmetic.v @@ -0,0 +1,493 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Arithmetic Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Arithmetic instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.stack. + +Definition add (evm : Evm) : M unit := + (* + Adds the top two elements of the stack together, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_add" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sub (evm : Evm) : M unit := + (* + Subtracts the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_sub" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mul (evm : Evm) : M unit := + (* + Multiply the top two elements of the stack, and pushes the result back + on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + do* M.assign "result" [[ + M.get_field ~(| M.get_local ~(| "x" |), "wrapping_mul" |) ~(| + M.get_local ~(| "y" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition div (evm : Evm) : M unit := + (* + Integer division of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "divisor" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "quotient" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sdiv (evm : Evm) : M unit := + (* + Signed integer division of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "dividend" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "divisor" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "quotient" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mod (evm : Evm) : M unit := + (* + Modulo remainder of the top two elements of the stack. Pushes the result + back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "remainder" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition smod (evm : Evm) : M unit := + (* + Signed modulo remainder of the top two elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "y" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_signed" |) ~(| + M.get_local ~(| "remainder" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition addmod (evm : Evm) : M unit := + (* + Modulo addition of the top 2 elements with the 3rd element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mulmod (evm : Evm) : M unit := + (* + Modulo multiplication of the top 2 elements with the 3rd element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "y" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "z" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_MID + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition exp (evm : Evm) : M unit := + (* + Exponential operation of the top 2 elements. Pushes the result back on + the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "base" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "exponent_bits" [[ + M.get_field ~(| M.get_local ~(| "exponent" |), "bit_length" |) ~(| + + |) in + ]] in + do* M.assign "exponent_bytes" [[ + (* TODO expression *) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "pow" |) ~(| + M.get_local ~(| "base" |), + M.get_local ~(| "exponent" |), + (* TODO expression *) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signextend (evm : Evm) : M unit := + (* + Sign extend operation. In other words, extend a signed number which + fits in N bytes to 32 bytes. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_num" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/bitwise.ast b/coq/ethereum/tangerine_whistle/vm/instructions/bitwise.ast new file mode 100644 index 0000000000..73dc9f4a45 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/bitwise.ast @@ -0,0 +1,418 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Bitwise Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM bitwise instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='bitwise_and', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise AND operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitAnd(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_or', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise OR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitOr(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_xor', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise XOR operation of the top 2 elements of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='y', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + BinOp( + left=Name(id='x', ctx=Load()), + op=BitXor(), + right=Name(id='y', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='bitwise_not', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Bitwise NOT operation of the top element of the stack. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + UnaryOp( + op=Invert(), + operand=Name(id='x', ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_byte', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For a word (defined by next top element of the stack), retrieve the\n Nth byte (0-indexed and defined by top element of stack) from the\n left (most significant) to right (least significant).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='byte_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='byte_index', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='extra_bytes_to_right', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=31)], + keywords=[]), + op=Sub(), + right=Name(id='byte_index', ctx=Load()))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=RShift(), + right=BinOp( + left=Name(id='extra_bytes_to_right', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=8)], + keywords=[])))), + Assign( + targets=[ + Name(id='word', ctx=Store())], + value=BinOp( + left=Name(id='word', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Name(id='word', ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/bitwise.v b/coq/ethereum/tangerine_whistle/vm/instructions/bitwise.v new file mode 100644 index 0000000000..45716bf9c9 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/bitwise.v @@ -0,0 +1,196 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Bitwise Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM bitwise instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.stack. + +Definition bitwise_and (evm : Evm) : M unit := + (* + Bitwise AND operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_or (evm : Evm) : M unit := + (* + Bitwise OR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_xor (evm : Evm) : M unit := + (* + Bitwise XOR operation of the top 2 elements of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "y" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition bitwise_not (evm : Evm) : M unit := + (* + Bitwise NOT operation of the top element of the stack. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition get_byte (evm : Evm) : M unit := + (* + For a word (defined by next top element of the stack), retrieve the + Nth byte (0-indexed and defined by top element of stack) from the + left (most significant) to right (least significant). + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "byte_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "word" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/block.ast b/coq/ethereum/tangerine_whistle/vm/instructions/block.ast new file mode 100644 index 0000000000..cc66857e82 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/block.ast @@ -0,0 +1,437 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Block Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM block instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_BLOCK_HASH'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='block_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the hash of one of the 256 most recent complete blocks onto the\n stack. The block number to hash is present at the top of the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BLOCK_HASH', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='max_block_number', ctx=Store())], + value=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]))), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='block_number', ctx=Load())]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='max_block_number', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Constant(value=b'\x00'))], + orelse=[ + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load()), + op=Sub(), + right=Name(id='block_number', ctx=Load()))), + ctx=Load()))]), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='coinbase', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's beneficiary address (address of the block miner)\n onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's timestamp onto the stack. Here the timestamp\n being referred is actually the unix timestamp in seconds.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='time', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='number', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's number onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's difficulty onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_limit', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Push the current block's gas limit onto the stack.\n\n Here the current block refers to the block in which the currently\n executing transaction/call resides.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_limit', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/block.v b/coq/ethereum/tangerine_whistle/vm/instructions/block.v new file mode 100644 index 0000000000..f28248f8ab --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/block.v @@ -0,0 +1,213 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Block Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM block instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.stack. + +Definition block_hash (evm : Evm) : M unit := + (* + Push the hash of one of the 256 most recent complete blocks onto the + stack. The block number to hash is present at the top of the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "block_number" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BLOCK_HASH + |) ]] in + do* M.assign "max_block_number" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition coinbase (evm : Evm) : M unit := + (* + Push the current block's beneficiary address (address of the block miner) + onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "coinbase" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition timestamp (evm : Evm) : M unit := + (* + Push the current block's timestamp onto the stack. Here the timestamp + being referred is actually the unix timestamp in seconds. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "env" |), "time" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition number (evm : Evm) : M unit := + (* + Push the current block's number onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "number" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition difficulty (evm : Evm) : M unit := + (* + Push the current block's difficulty onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "difficulty" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_limit (evm : Evm) : M unit := + (* + Push the current block's gas limit onto the stack. + + Here the current block refers to the block in which the currently + executing transaction/call resides. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_limit" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/comparison.ast b/coq/ethereum/tangerine_whistle/vm/instructions/comparison.ast new file mode 100644 index 0000000000..0a126cb709 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/comparison.ast @@ -0,0 +1,514 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Comparison Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Comparison instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is less than the next top element. Pushes the\n result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_less_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed less-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is greater than the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='signed_greater_than', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Signed greater-than comparison.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_signed', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to the next top element. Pushes\n the result back on the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='left', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='right', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='left', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='right', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='is_zero', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if the top element is equal to 0. Pushes the result back on the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='x', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='result', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/comparison.v b/coq/ethereum/tangerine_whistle/vm/instructions/comparison.v new file mode 100644 index 0000000000..1a7b865f20 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/comparison.v @@ -0,0 +1,266 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Comparison Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Comparison instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.stack. + +Definition less_than (evm : Evm) : M unit := + (* + Checks if the top element is less than the next top element. Pushes the + result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_less_than (evm : Evm) : M unit := + (* + Signed less-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition greater_than (evm : Evm) : M unit := + (* + Checks if the top element is greater than the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition signed_greater_than (evm : Evm) : M unit := + (* + Signed greater-than comparison. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* M.assign "right" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_signed" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition equal (evm : Evm) : M unit := + (* + Checks if the top element is equal to the next top element. Pushes + the result back on the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "left" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "right" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition is_zero (evm : Evm) : M unit := + (* + Checks if the top element is equal to 0. Pushes the result back on the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "x" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "result" [[ + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "result" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/control_flow.ast b/coq/ethereum/tangerine_whistle/vm/instructions/control_flow.ast new file mode 100644 index 0000000000..f06948f4c0 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/control_flow.ast @@ -0,0 +1,371 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Control Flow Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM control flow instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_HIGH'), + alias(name='GAS_JUMPDEST'), + alias(name='GAS_MID'), + alias(name='charge_gas')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='InvalidJumpDestError')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='stop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stop further execution of EVM code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Pass(), + Pass(), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jump', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the location specified by the top of the\n stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_MID', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='jump_dest', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpi', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Alter the program counter to the specified location if and only if a\n condition is true. If the condition is not true, then the program counter\n would increase only by 1.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='jump_dest', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='conditional_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_HIGH', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='conditional_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Name(id='jump_dest', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='valid_jump_destinations', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidJumpDestError', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='destination', ctx=Store())], + value=Name(id='jump_dest', ctx=Load()))])]), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store())], + value=Name(id='destination', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='pc', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push onto the stack the value of the program counter after reaching the\n current instruction and without increasing it for the next instruction.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gas_left', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the amount of available gas (including the corresponding reduction\n for the cost of this instruction) onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='jumpdest', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Mark a valid destination for jumps. This is a noop, present only\n to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is\n valid.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_JUMPDEST', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/control_flow.v b/coq/ethereum/tangerine_whistle/vm/instructions/control_flow.v new file mode 100644 index 0000000000..5cd448277e --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/control_flow.v @@ -0,0 +1,180 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Control Flow Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM control flow instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.exceptions. +Require ethereum.tangerine_whistle.vm.stack. + +Definition stop (evm : Evm) : M unit := + (* + Stop further execution of EVM code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jump (evm : Evm) : M unit := + (* + Alter the program counter to the location specified by the top of the + stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_MID + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition jumpi (evm : Evm) : M unit := + (* + Alter the program counter to the specified location if and only if a + condition is true. If the condition is not true, then the program counter + would increase only by 1. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "jump_dest" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "conditional_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_HIGH + |) ]] in + (* TODO statement *) + (* TODO assignment *) + M.pure tt. + +Definition pc (evm : Evm) : M unit := + (* + Push onto the stack the value of the program counter after reaching the + current instruction and without increasing it for the next instruction. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "pc" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gas_left (evm : Evm) : M unit := + (* + Push the amount of available gas (including the corresponding reduction + for the cost of this instruction) onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition jumpdest (evm : Evm) : M unit := + (* + Mark a valid destination for jumps. This is a noop, present only + to be used by `JUMP` and `JUMPI` opcodes to verify that their jump is + valid. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_JUMPDEST + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/environment.ast b/coq/ethereum/tangerine_whistle/vm/instructions/environment.ast new file mode 100644 index 0000000000..15f88ad9cc --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/environment.ast @@ -0,0 +1,1199 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Environmental Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM environment related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_account')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='to_address')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read'), + alias(name='memory_write')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BALANCE'), + alias(name='GAS_BASE'), + alias(name='GAS_COPY'), + alias(name='GAS_EXTERNAL'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='address', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the current executing account to the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='balance', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the balance of the given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BALANCE', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='balance', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='origin', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the original transaction sender to the stack.\n The origin address can only be an EOA.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='origin', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='caller', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes the address of the caller onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callvalue', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the value (in wei) sent with the call onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldataload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push a word (32 bytes) of the input data belonging to the current\n environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='start_index', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatasize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of input data in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='calldatacopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the input data in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load()), + Name(id='data_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of code running in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='codecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy a portion of the code in current environment to memory.\n\n This will also expand the memory, in case that the memory is insufficient\n to store the data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='gasprice', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the gas price used in current environment onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='gas_price', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodesize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the code size of a given account onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_EXTERNAL', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='codesize', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='codesize', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='extcodecopy', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Copy a portion of an account's code to memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='copy_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_COPY', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_EXTERNAL', ctx=Load()), + op=Add(), + right=Name(id='copy_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='code', ctx=Load()), + Name(id='code_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/environment.v b/coq/ethereum/tangerine_whistle/vm/instructions/environment.v new file mode 100644 index 0000000000..0ecd2769c2 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/environment.v @@ -0,0 +1,552 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Environmental Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM environment related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.tangerine_whistle.state. +Require ethereum.tangerine_whistle.utils.address. +Require ethereum.tangerine_whistle.vm.memory. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.stack. + +Definition address (evm : Evm) : M unit := + (* + Pushes the address of the current executing account to the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition balance (evm : Evm) : M unit := + (* + Pushes the balance of the given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BALANCE + |) ]] in + do* M.assign "balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "balance" |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "balance" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition origin (evm : Evm) : M unit := + (* + Pushes the address of the original transaction sender to the stack. + The origin address can only be an EOA. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "origin" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition caller (evm : Evm) : M unit := + (* + Pushes the address of the caller onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callvalue (evm : Evm) : M unit := + (* + Push the value (in wei) sent with the call onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldataload (evm : Evm) : M unit := + (* + Push a word (32 bytes) of the input data belonging to the current + environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "start_index" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "value" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatasize (evm : Evm) : M unit := + (* + Push the size of input data in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition calldatacopy (evm : Evm) : M unit := + (* + Copy a portion of the input data in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "data_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |), + M.get_local ~(| "data_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codesize (evm : Evm) : M unit := + (* + Push the size of code running in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "code" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition codecopy (evm : Evm) : M unit := + (* + Copy a portion of the code in current environment to memory. + + This will also expand the memory, in case that the memory is insufficient + to store the data. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition gasprice (evm : Evm) : M unit := + (* + Push the gas price used in current environment onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "gas_price" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodesize (evm : Evm) : M unit := + (* + Push the code size of a given account onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_EXTERNAL + |) ]] in + do* M.assign "codesize" [[ + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "codesize" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition extcodecopy (evm : Evm) : M unit := + (* + Copy a portion of an account's code to memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "code_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "copy_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "address" |) + |), "code" |) in + ]] in + do* M.assign "value" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "code" |), + M.get_local ~(| "code_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* [[ vm.memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/keccak.ast b/coq/ethereum/tangerine_whistle/vm/instructions/keccak.ast new file mode 100644 index 0000000000..f8eb00fc41 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/keccak.ast @@ -0,0 +1,205 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Keccak Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM keccak instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_KECCAK256'), + alias(name='GAS_KECCAK256_WORD'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='keccak', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Pushes to the stack the Keccak-256 hash of a region of memory.\n\n This also expands the memory, in case the memory is insufficient to\n access the data's memory location.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='words', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Assign( + targets=[ + Name(id='word_gas_cost', ctx=Store())], + value=BinOp( + left=Name(id='GAS_KECCAK256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='words', ctx=Load()))), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_KECCAK256', ctx=Load()), + op=Add(), + right=Name(id='word_gas_cost', ctx=Load())), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Name(id='hash', ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/keccak.v b/coq/ethereum/tangerine_whistle/vm/instructions/keccak.v new file mode 100644 index 0000000000..d2da5e97bf --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/keccak.v @@ -0,0 +1,89 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Keccak Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM keccak instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.hash. +Require ethereum.utils.numeric. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.memory. +Require ethereum.tangerine_whistle.vm.stack. + +Definition keccak (evm : Evm) : M unit := + (* + Pushes to the stack the Keccak-256 hash of a region of memory. + + This also expands the memory, in case the memory is insufficient to + access the data's memory location. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "words" [[ + (* TODO expression *) in + ]] in + do* M.assign "word_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "memory_start_index" |), + M.get_local ~(| "size" |) + |) in + ]] in + do* M.assign "hash" [[ + ethereum.crypto.hash.keccak256 ~(| + M.get_local ~(| "data" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + M.get_local ~(| "hash" |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/log.ast b/coq/ethereum/tangerine_whistle/vm/instructions/log.ast new file mode 100644 index 0000000000..d3bf292c44 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/log.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Logging Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM logging instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_LOG'), + alias(name='GAS_LOG_DATA'), + alias(name='GAS_LOG_TOPIC'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop')], + level=2), + FunctionDef( + name='log_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_topics', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Appends a log entry, having `num_topics` topics, to the evm logs.\n\n This will also expand the memory if the data (required by the log entry)\n corresponding to the memory is not accessible.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n num_topics :\n The number of topics to be included in the log entry.\n\n ')), + Assign( + targets=[ + Name(id='memory_start_index', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='topics', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='topic', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='topics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='topic', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=BinOp( + left=BinOp( + left=Name(id='GAS_LOG', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_DATA', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + op=Add(), + right=BinOp( + left=Name(id='GAS_LOG_TOPIC', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_topics', ctx=Load())], + keywords=[]))), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='log_entry', ctx=Store())], + value=Call( + func=Name(id='Log', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='address', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='topics', + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='topics', ctx=Load())], + keywords=[])), + keyword( + arg='data', + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_index', ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load()), + op=Add(), + right=Tuple( + elts=[ + Name(id='log_entry', ctx=Load())], + ctx=Load()))), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='log0', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='log1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='log2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='log3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='log4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='log_n', ctx=Load())], + keywords=[ + keyword( + arg='num_topics', + value=Constant(value=4))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/log.v b/coq/ethereum/tangerine_whistle/vm/instructions/log.v new file mode 100644 index 0000000000..11d0131f08 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/log.v @@ -0,0 +1,77 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Logging Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM logging instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.tangerine_whistle.blocks. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.memory. +Require ethereum.tangerine_whistle.vm.stack. + +Definition log_n (evm : Evm) (num_topics : U256) : M unit := + (* + Appends a log entry, having `num_topics` topics, to the evm logs. + + This will also expand the memory if the data (required by the log entry) + corresponding to the memory is not accessible. + + Parameters + ---------- + evm : + The current EVM frame. + num_topics : + The number of topics to be included in the log entry. + + *) + do* M.assign "memory_start_index" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "topics" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "log_entry" [[ + blocks.Log ~(| + + |) in + ]] in + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/memory.ast b/coq/ethereum/tangerine_whistle/vm/instructions/memory.ast new file mode 100644 index 0000000000..47efb13e55 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/memory.ast @@ -0,0 +1,463 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM Memory instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='calculate_gas_extend_memory'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='mstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a word to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mstore8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Stores a byte to memory.\n This also expands the memory, if the memory is\n insufficient to store the word.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='normalized_bytes_value', ctx=Store())], + value=Call( + func=Name(id='Bytes', ctx=Load()), + args=[ + List( + elts=[ + BinOp( + left=Name(id='value', ctx=Load()), + op=BitAnd(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Name(id='normalized_bytes_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='mload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load word from memory.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_VERY_LOW', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='start_position', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='msize', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Push the size of active memory in bytes onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/memory.v b/coq/ethereum/tangerine_whistle/vm/instructions/memory.v new file mode 100644 index 0000000000..483c212366 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/memory.v @@ -0,0 +1,202 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM Memory instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.memory. +Require ethereum.tangerine_whistle.vm.stack. + +Definition mstore (evm : Evm) : M unit := + (* + Stores a word to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mstore8 (evm : Evm) : M unit := + (* + Stores a byte to memory. + This also expands the memory, if the memory is + insufficient to store the word. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "normalized_bytes_value" [[ + ethereum_types.bytes.Bytes ~(| + (* TODO expression *) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + M.get_local ~(| "normalized_bytes_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition mload (evm : Evm) : M unit := + (* + Load word from memory. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "value" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + M.get_local ~(| "start_position" |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition msize (evm : Evm) : M unit := + (* + Push the size of active memory in bytes onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) + |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/stack.ast b/coq/ethereum/tangerine_whistle/vm/instructions/stack.ast new file mode 100644 index 0000000000..95cfc0b6cf --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/stack.ast @@ -0,0 +1,1083 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM stack related instructions.\n')), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='stack')], + level=2), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackUnderflowError')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_BASE'), + alias(name='GAS_VERY_LOW'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='buffer_read')], + level=2), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Remove item from stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_BASE', ctx=Load())], + keywords=[])), + Pass(), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='push_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='num_bytes', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes a N-byte immediate onto the stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n num_bytes :\n The number of immediate bytes to be read from the code and pushed to\n the stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data_to_push', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_push', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='num_bytes', ctx=Load())], + keywords=[])))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='dup_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Duplicate the Nth stack item (from top of the stack) to the top of stack.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be duplicated\n to the top of stack.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='data_to_duplicate', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='data_to_duplicate', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='swap_n', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='item_number', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Swap the top and the `item_number` element of the stack, where\n the top of the stack is position zero.\n\n If `item_number` is zero, this function does nothing (which should not be\n possible, since there is no `SWAP0` instruction).\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n item_number :\n The stack item number (0-indexed from top of stack) to be swapped\n with the top of stack element.\n\n ')), + Pass(), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_VERY_LOW', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='item_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Store())], + ctx=Store())], + value=Tuple( + elts=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=BinOp( + left=UnaryOp( + op=USub(), + operand=Constant(value=1)), + op=Sub(), + right=Name(id='item_number', ctx=Load())), + ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())], + ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + Assign( + targets=[ + Name(id='push1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='push2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='push3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='push4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='push5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='push6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='push7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='push8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='push9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='push10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='push11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='push12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='push13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='push14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='push15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='push16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=16))])), + Assign( + targets=[ + Name(id='push17', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=17))])), + Assign( + targets=[ + Name(id='push18', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=18))])), + Assign( + targets=[ + Name(id='push19', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=19))])), + Assign( + targets=[ + Name(id='push20', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=20))])), + Assign( + targets=[ + Name(id='push21', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=21))])), + Assign( + targets=[ + Name(id='push22', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=22))])), + Assign( + targets=[ + Name(id='push23', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=23))])), + Assign( + targets=[ + Name(id='push24', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=24))])), + Assign( + targets=[ + Name(id='push25', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=25))])), + Assign( + targets=[ + Name(id='push26', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=26))])), + Assign( + targets=[ + Name(id='push27', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=27))])), + Assign( + targets=[ + Name(id='push28', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=28))])), + Assign( + targets=[ + Name(id='push29', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=29))])), + Assign( + targets=[ + Name(id='push30', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=30))])), + Assign( + targets=[ + Name(id='push31', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=31))])), + Assign( + targets=[ + Name(id='push32', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='push_n', ctx=Load())], + keywords=[ + keyword( + arg='num_bytes', + value=Constant(value=32))])), + Assign( + targets=[ + Name(id='dup1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=0))])), + Assign( + targets=[ + Name(id='dup2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='dup3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='dup4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='dup5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='dup6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='dup7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='dup8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='dup9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='dup10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='dup11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='dup12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='dup13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='dup14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='dup15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='dup16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='dup_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap1', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=1))])), + Assign( + targets=[ + Name(id='swap2', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=2))])), + Assign( + targets=[ + Name(id='swap3', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=3))])), + Assign( + targets=[ + Name(id='swap4', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=4))])), + Assign( + targets=[ + Name(id='swap5', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=5))])), + Assign( + targets=[ + Name(id='swap6', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=6))])), + Assign( + targets=[ + Name(id='swap7', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=7))])), + Assign( + targets=[ + Name(id='swap8', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=8))])), + Assign( + targets=[ + Name(id='swap9', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=9))])), + Assign( + targets=[ + Name(id='swap10', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=10))])), + Assign( + targets=[ + Name(id='swap11', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=11))])), + Assign( + targets=[ + Name(id='swap12', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=12))])), + Assign( + targets=[ + Name(id='swap13', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=13))])), + Assign( + targets=[ + Name(id='swap14', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=14))])), + Assign( + targets=[ + Name(id='swap15', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=15))])), + Assign( + targets=[ + Name(id='swap16', ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='swap_n', ctx=Load())], + keywords=[ + keyword( + arg='item_number', + value=Constant(value=16))]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/stack.v b/coq/ethereum/tangerine_whistle/vm/instructions/stack.v new file mode 100644 index 0000000000..5d773992f7 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/stack.v @@ -0,0 +1,153 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM stack related instructions. +*) + +Require functools. +Require ethereum_types.numeric. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.exceptions. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.memory. + +Definition pop (evm : Evm) : M unit := + (* + Remove item from stack. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* [[ M.get_field ~(| __init__.stack, "pop" |) ~(| + M.get_field ~(| evm, "stack" |) + |) ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_BASE + |) ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition push_n (evm : Evm) (num_bytes : int) : M unit := + (* + Pushes a N-byte immediate onto the stack. + + Parameters + ---------- + evm : + The current EVM frame. + + num_bytes : + The number of immediate bytes to be read from the code and pushed to + the stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + do* M.assign "data_to_push" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + memory.buffer_read ~(| + M.get_field ~(| evm, "code" |), + ethereum_types.numeric.U256 ~(| + (* TODO expression *) + |), + ethereum_types.numeric.U256 ~(| + num_bytes + |) + |) + |) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_push" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + (* TODO expression *) + ]] in + M.pure tt. + +Definition dup_n (evm : Evm) (item_number : int) : M unit := + (* + Duplicate the Nth stack item (from top of the stack) to the top of stack. + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be duplicated + to the top of stack. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + do* M.assign "data_to_duplicate" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| __init__.stack, "push" |) ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "data_to_duplicate" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition swap_n (evm : Evm) (item_number : int) : M unit := + (* + Swap the top and the `item_number` element of the stack, where + the top of the stack is position zero. + + If `item_number` is zero, this function does nothing (which should not be + possible, since there is no `SWAP0` instruction). + + Parameters + ---------- + evm : + The current EVM frame. + + item_number : + The stack item number (0-indexed from top of stack) to be swapped + with the top of stack element. + + *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_VERY_LOW + |) ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/storage.ast b/coq/ethereum/tangerine_whistle/vm/instructions/storage.ast new file mode 100644 index 0000000000..7ce9b2f17f --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/storage.ast @@ -0,0 +1,278 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Storage Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM storage related instructions.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='state', + names=[ + alias(name='get_storage'), + alias(name='set_storage')], + level=3), + ImportFrom( + names=[ + alias(name='Evm')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_SLOAD'), + alias(name='GAS_STORAGE_CLEAR_REFUND'), + alias(name='GAS_STORAGE_SET'), + alias(name='GAS_STORAGE_UPDATE'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='sload', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Loads to the stack, the value corresponding to a certain key from the\n storage of the current account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ')), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_SLOAD', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sstore', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Stores a value at a certain key in the current context's storage.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n\n ")), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[]), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='new_value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='current_value', ctx=Store())], + value=Call( + func=Name(id='get_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_SET', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_STORAGE_UPDATE', ctx=Load()))]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='new_value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + Compare( + left=Name(id='current_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='GAS_STORAGE_CLEAR_REFUND', ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='new_value', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/storage.v b/coq/ethereum/tangerine_whistle/vm/instructions/storage.v new file mode 100644 index 0000000000..1bc4a4a5aa --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/storage.v @@ -0,0 +1,108 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Storage Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM storage related instructions. +*) + +Require ethereum_types.numeric. +Require ethereum.tangerine_whistle.state. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.stack. + +Definition sload (evm : Evm) : M unit := + (* + Loads to the stack, the value corresponding to a certain key from the + storage of the current account. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + gas.GAS_SLOAD + |) ]] in + do* M.assign "value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + do* [[ stack.push ~(| + M.get_field ~(| evm, "stack" |), + M.get_local ~(| "value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition sstore (evm : Evm) : M unit := + (* + Stores a value at a certain key in the current context's storage. + + Parameters + ---------- + evm : + The current EVM frame. + + *) + do* M.assign "key" [[ + M.get_field ~(| stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |), "to_be_bytes32" |) ~(| + + |) in + ]] in + do* M.assign "new_value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "current_value" [[ + state.get_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + do* [[ state.set_storage ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "key" |), + M.get_local ~(| "new_value" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/system.ast b/coq/ethereum/tangerine_whistle/vm/instructions/system.ast new file mode 100644 index 0000000000..8f5868170d --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/system.ast @@ -0,0 +1,1996 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) System Instructions\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementations of the EVM system related instructions.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + module='state', + names=[ + alias(name='account_exists'), + alias(name='account_has_code_or_nonce'), + alias(name='get_account'), + alias(name='increment_nonce'), + alias(name='set_account_balance')], + level=3), + ImportFrom( + module='utils.address', + names=[ + alias(name='compute_contract_address'), + alias(name='to_address')], + level=3), + ImportFrom( + names=[ + alias(name='Evm'), + alias(name='Message'), + alias(name='incorporate_child_on_error'), + alias(name='incorporate_child_on_success')], + level=2), + ImportFrom( + module='gas', + names=[ + alias(name='GAS_CALL'), + alias(name='GAS_CALL_VALUE'), + alias(name='GAS_CREATE'), + alias(name='GAS_NEW_ACCOUNT'), + alias(name='GAS_SELF_DESTRUCT'), + alias(name='GAS_SELF_DESTRUCT_NEW_ACCOUNT'), + alias(name='GAS_ZERO'), + alias(name='REFUND_SELF_DESTRUCT'), + alias(name='calculate_gas_extend_memory'), + alias(name='calculate_message_call_gas'), + alias(name='charge_gas'), + alias(name='max_message_call_gas')], + level=2), + ImportFrom( + module='memory', + names=[ + alias(name='memory_read_bytes'), + alias(name='memory_write')], + level=2), + ImportFrom( + module='stack', + names=[ + alias(name='pop'), + alias(name='push')], + level=2), + FunctionDef( + name='create', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Creates a new account with associated code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_create_message')], + level=3), + Assign( + targets=[ + Name(id='endowment', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_CREATE', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='create_message_gas', ctx=Store())], + value=Call( + func=Name(id='max_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Sub(), + value=Name(id='create_message_gas', ctx=Load())), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='sender', ctx=Store())], + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='sender_address', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='contract_address', ctx=Store())], + value=Call( + func=Name(id='compute_contract_address', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='nonce', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='balance', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='endowment', ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='sender', ctx=Load()), + attr='nonce', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value=2), + op=Pow(), + right=Constant(value=64)), + op=Sub(), + right=Constant(value=1))], + keywords=[])]), + Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())])]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='create_message_gas', ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='contract_address', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='increment_nonce', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + keyword( + arg='target', + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='gas', + value=Name(id='create_message_gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='endowment', ctx=Load())), + keyword( + arg='data', + value=Constant(value=b'')), + keyword( + arg='code', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='contract_address', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Constant(value=None)), + keyword( + arg='should_transfer_value', + value=Constant(value=True)), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])], + keywords=[]))])])]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='return_', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halts execution returning output data.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='memory_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_ZERO', ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_start_position', ctx=Load()), + Name(id='memory_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load())), + arg( + arg='gas', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='caller', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='to', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='code_address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='should_transfer_value', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='memory_input_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_input_size', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='memory_output_size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Perform the core logic of the `CALL*` family of opcodes.\n ')), + ImportFrom( + module='vm.interpreter', + names=[ + alias(name='STACK_DEPTH_LIMIT'), + alias(name='process_message')], + level=3), + If( + test=Compare( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Name(id='gas', ctx=Load())), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Return()], + orelse=[]), + Assign( + targets=[ + Name(id='call_data', ctx=Store())], + value=Call( + func=Name(id='memory_read_bytes', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='code_address', ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='child_message', ctx=Store())], + value=Call( + func=Name(id='Message', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Name(id='caller', ctx=Load())), + keyword( + arg='target', + value=Name(id='to', ctx=Load())), + keyword( + arg='gas', + value=Name(id='gas', ctx=Load())), + keyword( + arg='value', + value=Name(id='value', ctx=Load())), + keyword( + arg='data', + value=Name(id='call_data', ctx=Load())), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='current_target', + value=Name(id='to', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + keyword( + arg='code_address', + value=Name(id='code_address', ctx=Load())), + keyword( + arg='should_transfer_value', + value=Name(id='should_transfer_value', ctx=Load())), + keyword( + arg='parent_evm', + value=Name(id='evm', ctx=Load()))])), + Assign( + targets=[ + Name(id='child_evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='child_message', ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_error', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='incorporate_child_on_success', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='child_evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[]))]), + Assign( + targets=[ + Name(id='actual_output_size', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='memory_output_size', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Name(id='memory_write', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='child_evm', ctx=Load()), + attr='output', + ctx=Load()), + slice=Slice( + upper=Name(id='actual_output_size', ctx=Load())), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='_account_exists', ctx=Store())], + value=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='to', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='create_gas_cost', ctx=Store())], + value=IfExp( + test=Name(id='_account_exists', ctx=Load()), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_NEW_ACCOUNT', ctx=Load()))), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='create_gas_cost', ctx=Load())), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='to', ctx=Load()), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='callcode', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into this account with alternative account’s code.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='to', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='transfer_gas_cost', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + orelse=Name(id='GAS_CALL_VALUE', ctx=Load()))), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + BinOp( + left=Name(id='GAS_CALL', ctx=Load()), + op=Add(), + right=Name(id='transfer_gas_cost', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Assign( + targets=[ + Name(id='sender_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + If( + test=Compare( + left=Name(id='sender_balance', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='value', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='push', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Name(id='value', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='to', ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=True), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[]))]), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='selfdestruct', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Halt execution and register account for later deletion.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='beneficiary', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='gas_cost', ctx=Store())], + value=Name(id='GAS_SELF_DESTRUCT', ctx=Load())), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='account_exists', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[])), + body=[ + AugAssign( + target=Name(id='gas_cost', ctx=Store()), + op=Add(), + value=Name(id='GAS_SELF_DESTRUCT_NEW_ACCOUNT', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='originator', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load())), + Assign( + targets=[ + Name(id='refunded_accounts', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load())), + While( + test=Compare( + left=Name(id='parent_evm', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='refunded_accounts', ctx=Load()), + attr='update', + ctx=Load()), + args=[ + Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='originator', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='refunded_accounts', ctx=Load())]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Store()), + op=Add(), + value=Name(id='REFUND_SELF_DESTRUCT', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='gas_cost', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='beneficiary_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Assign( + targets=[ + Name(id='originator_balance', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='get_account', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load())], + keywords=[]), + attr='balance', + ctx=Load())), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='beneficiary', ctx=Load()), + BinOp( + left=Name(id='beneficiary_balance', ctx=Load()), + op=Add(), + right=Name(id='originator_balance', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account_balance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='originator', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='originator', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Store())], + value=Constant(value=False)), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delegatecall', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Message-call into an account.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='gas', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='code_address', ctx=Store())], + value=Call( + func=Name(id='to_address', ctx=Load()), + args=[ + Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_input_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_start_position', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='memory_output_size', ctx=Store())], + value=Call( + func=Name(id='pop', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='extend_memory', ctx=Store())], + value=Call( + func=Name(id='calculate_gas_extend_memory', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + List( + elts=[ + Tuple( + elts=[ + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load())], + ctx=Load()), + Tuple( + elts=[ + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_call_gas', ctx=Store())], + value=Call( + func=Name(id='calculate_message_call_gas', ctx=Load()), + args=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Name(id='gas', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()), + Name(id='GAS_CALL', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='cost', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='cost', + ctx=Load()))], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Store()), + op=Add(), + value=BinOp( + left=Constant(value=b'\x00'), + op=Mult(), + right=Attribute( + value=Name(id='extend_memory', ctx=Load()), + attr='expand_by', + ctx=Load()))), + Expr( + value=Call( + func=Name(id='generic_call', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Attribute( + value=Name(id='message_call_gas', ctx=Load()), + attr='stipend', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='code_address', ctx=Load()), + Constant(value=False), + Name(id='memory_input_start_position', ctx=Load()), + Name(id='memory_input_size', ctx=Load()), + Name(id='memory_output_start_position', ctx=Load()), + Name(id='memory_output_size', ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/instructions/system.v b/coq/ethereum/tangerine_whistle/vm/instructions/system.v new file mode 100644 index 0000000000..b06a9867ef --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/instructions/system.v @@ -0,0 +1,528 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) System Instructions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementations of the EVM system related instructions. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.tangerine_whistle.fork_types. +Require ethereum.tangerine_whistle.state. +Require ethereum.tangerine_whistle.utils.address. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.memory. +Require ethereum.tangerine_whistle.vm.stack. + +Definition create (evm : Evm) : M unit := + (* + Creates a new account with associated code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + (* TODO statement *) + do* M.assign "endowment" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "create_message_gas" [[ + gas.max_message_call_gas ~(| + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |) + |) in + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "gas_left" |) ]] [[ + M.get_local ~(| "create_message_gas" |) + ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_address" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "sender" [[ + state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "sender_address" |) + |) in + ]] in + do* M.assign "contract_address" [[ + utils.address.compute_contract_address ~(| + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "nonce" |) + |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition return_ (evm : Evm) : M unit := + (* + Halts execution returning output data. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "memory_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + (* TODO assignment *) + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition generic_call (evm : Evm) (gas : Uint) (value : U256) (caller : Address) (to : Address) (code_address : Address) (should_transfer_value : bool) (memory_input_start_position : U256) (memory_input_size : U256) (memory_output_start_position : U256) (memory_output_size : U256) : M unit := + (* + Perform the core logic of the `CALL*` family of opcodes. + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "call_data" [[ + memory.memory_read_bytes ~(| + M.get_field ~(| evm, "memory" |), + memory_input_start_position, + memory_input_size + |) in + ]] in + do* M.assign "code" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + code_address + |), "code" |) in + ]] in + do* M.assign "child_message" [[ + __init__.Message ~(| + + |) in + ]] in + do* M.assign "child_evm" [[ + M.get_local ~(| "process_message" |) ~(| + M.get_local ~(| "child_message" |), + M.get_field ~(| evm, "env" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "actual_output_size" [[ + M.get_local ~(| "min" |) ~(| + memory_output_size, + ethereum_types.numeric.U256 ~(| + M.get_local ~(| "len" |) ~(| + M.get_field ~(| M.get_local ~(| "child_evm" |), "output" |) + |) + |) + |) in + ]] in + do* [[ memory.memory_write ~(| + M.get_field ~(| evm, "memory" |), + memory_output_start_position, + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition call (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "to" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "_account_exists" [[ + state.account_exists ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "to" |) + |) in + ]] in + do* M.assign "create_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition callcode (evm : Evm) : M unit := + (* + Message-call into this account with alternative account’s code. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "value" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "to" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "transfer_gas_cost" [[ + (* TODO expression *) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + M.get_local ~(| "value" |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + (* TODO expression *) + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* M.assign "sender_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) + |), "balance" |) in + ]] in + (* TODO statement *) + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. + +Definition selfdestruct (evm : Evm) : M unit := + (* + Halt execution and register account for later deletion. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "beneficiary" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "gas_cost" [[ + gas.GAS_SELF_DESTRUCT in + ]] in + (* TODO statement *) + do* M.assign "originator" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |) in + ]] in + do* M.assign "refunded_accounts" [[ + M.get_field ~(| evm, "accounts_to_delete" |) in + ]] in + do* M.assign "parent_evm" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "parent_evm" |) in + ]] in + (* TODO statement *) + (* TODO statement *) + do* [[ gas.charge_gas ~(| + evm, + M.get_local ~(| "gas_cost" |) + |) ]] in + do* M.assign "beneficiary_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |) + |), "balance" |) in + ]] in + do* M.assign "originator_balance" [[ + M.get_field ~(| state.get_account ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |) + |), "balance" |) in + ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "beneficiary" |), + (* TODO expression *) + |) ]] in + do* [[ state.set_account_balance ~(| + M.get_field ~(| M.get_field ~(| evm, "env" |), "state" |), + M.get_local ~(| "originator" |), + ethereum_types.numeric.U256 ~(| + 0 + |) + |) ]] in + do* [[ M.get_field ~(| M.get_field ~(| evm, "accounts_to_delete" |), "add" |) ~(| + M.get_local ~(| "originator" |) + |) ]] in + (* TODO assignment *) + (* TODO statement *) + M.pure tt. + +Definition delegatecall (evm : Evm) : M unit := + (* + Message-call into an account. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "gas" [[ + ethereum_types.numeric.Uint ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "code_address" [[ + utils.address.to_address ~(| + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) + |) in + ]] in + do* M.assign "memory_input_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_input_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_start_position" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "memory_output_size" [[ + stack.pop ~(| + M.get_field ~(| evm, "stack" |) + |) in + ]] in + do* M.assign "extend_memory" [[ + gas.calculate_gas_extend_memory ~(| + M.get_field ~(| evm, "memory" |), + (* TODO expression *) + |) in + ]] in + do* M.assign "message_call_gas" [[ + gas.calculate_message_call_gas ~(| + ethereum_types.numeric.U256 ~(| + 0 + |), + M.get_local ~(| "gas" |), + ethereum_types.numeric.Uint ~(| + M.get_field ~(| evm, "gas_left" |) + |), + M.get_field ~(| M.get_local ~(| "extend_memory" |), "cost" |), + gas.GAS_CALL + |) in + ]] in + do* [[ gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "memory" |) ]] [[ + (* TODO expression *) + ]] in + do* [[ M.get_local ~(| "generic_call" |) ~(| + evm, + M.get_field ~(| M.get_local ~(| "message_call_gas" |), "stipend" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "value" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "caller" |), + M.get_field ~(| M.get_field ~(| evm, "message" |), "current_target" |), + M.get_local ~(| "code_address" |), + False, + M.get_local ~(| "memory_input_start_position" |), + M.get_local ~(| "memory_input_size" |), + M.get_local ~(| "memory_output_start_position" |), + M.get_local ~(| "memory_output_size" |) + |) ]] in + do* M.aug_assign [[ M.get_field ~(| evm, "pc" |) ]] [[ + ethereum_types.numeric.Uint ~(| + 1 + |) + ]] in + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/interpreter.ast b/coq/ethereum/tangerine_whistle/vm/interpreter.ast new file mode 100644 index 0000000000..4caa112e0e --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/interpreter.ast @@ -0,0 +1,975 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Interpreter\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nA straightforward interpreter that executes EVM code.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Set'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TransactionEnd'), + alias(name='evm_trace')], + level=0), + ImportFrom( + module='blocks', + names=[ + alias(name='Log')], + level=2), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=2), + ImportFrom( + module='state', + names=[ + alias(name='account_has_code_or_nonce'), + alias(name='begin_transaction'), + alias(name='commit_transaction'), + alias(name='destroy_storage'), + alias(name='move_ether'), + alias(name='rollback_transaction'), + alias(name='set_code'), + alias(name='touch_account')], + level=2), + ImportFrom( + module='vm', + names=[ + alias(name='Message')], + level=2), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_CODE_DEPOSIT'), + alias(name='charge_gas')], + level=2), + ImportFrom( + module='vm.precompiled_contracts.mapping', + names=[ + alias(name='PRE_COMPILED_CONTRACTS')], + level=2), + ImportFrom( + names=[ + alias(name='Environment'), + alias(name='Evm')], + level=1), + ImportFrom( + module='exceptions', + names=[ + alias(name='AddressCollision'), + alias(name='ExceptionalHalt'), + alias(name='InvalidOpcode'), + alias(name='StackDepthLimitError')], + level=1), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops'), + alias(name='op_implementation')], + level=1), + ImportFrom( + module='runtime', + names=[ + alias(name='get_valid_jump_destinations')], + level=1), + Assign( + targets=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1024)], + keywords=[])), + ClassDef( + name='MessageCallOutput', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Output of a particular message call\n\n Contains the following:\n\n 1. `gas_left`: remaining gas after execution.\n 2. `refund_counter`: gas to refund after execution.\n 3. `logs`: list of `Log` generated during execution.\n 4. `accounts_to_delete`: Contracts which have self-destructed.\n 5. `error`: The error from the execution if any.\n ')), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='accounts_to_delete', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n If `message.current` is empty then it creates a smart contract\n else it executes a call from the `message.caller` to the `message.target`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n\n env :\n External items required for EVM execution.\n\n Returns\n -------\n output : `MessageCallOutput`\n Output of the message call\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='is_collision', ctx=Store())], + value=Call( + func=Name(id='account_has_code_or_nonce', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=Name(id='is_collision', ctx=Load()), + body=[ + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]), + Call( + func=Name(id='AddressCollision', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_create_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[]))]), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='logs', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Log', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + value=Tuple(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='logs', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='logs', + ctx=Load())), + Assign( + targets=[ + Name(id='accounts_to_delete', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='accounts_to_delete', + ctx=Load())), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Name(id='tx_end', ctx=Store())], + value=Call( + func=Name(id='TransactionEnd', ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())], + keywords=[]), + op=Sub(), + right=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='tx_end', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='MessageCallOutput', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())), + keyword( + arg='refund_counter', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='logs', + value=Name(id='logs', ctx=Load())), + keyword( + arg='accounts_to_delete', + value=Name(id='accounts_to_delete', ctx=Load())), + keyword( + arg='error', + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()))]))], + decorator_list=[], + returns=Name(id='MessageCallOutput', ctx=Load())), + FunctionDef( + name='process_create_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.tangerine_whistle.vm.Evm`\n Items containing execution specific objects.\n ')), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='destroy_storage', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='process_message', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='contract_code', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Load())), + Assign( + targets=[ + Name(id='contract_code_gas', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='contract_code', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=Name(id='GAS_CODE_DEPOSIT', ctx=Load()))), + Try( + body=[ + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='contract_code_gas', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[ + Expr( + value=Call( + func=Name(id='set_code', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Name(id='contract_code', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + finalbody=[])], + orelse=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='process_message', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes a call to create a smart contract.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: :py:class:`~ethereum.tangerine_whistle.vm.Evm`\n Items containing execution specific objects\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='STACK_DEPTH_LIMIT', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='StackDepthLimitError', ctx=Load()), + args=[ + Constant(value='Stack depth limit reached')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='begin_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='touch_account', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='message', ctx=Load()), + attr='should_transfer_value', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Name(id='move_ether', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='caller', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='current_target', + ctx=Load()), + Attribute( + value=Name(id='message', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='execute_code', ctx=Load()), + args=[ + Name(id='message', ctx=Load()), + Name(id='env', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='rollback_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='commit_transaction', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='state', + ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load())), + FunctionDef( + name='execute_code', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='message', + annotation=Name(id='Message', ctx=Load())), + arg( + arg='env', + annotation=Name(id='Environment', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Executes bytecode present in the `message`.\n\n Parameters\n ----------\n message :\n Transaction specific items.\n env :\n External items required for EVM execution.\n\n Returns\n -------\n evm: `ethereum.vm.EVM`\n Items containing execution specific objects\n ')), + Assign( + targets=[ + Name(id='code', ctx=Store())], + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='get_valid_jump_destinations', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='evm', ctx=Store())], + value=Call( + func=Name(id='Evm', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='stack', + value=List(elts=[], ctx=Load())), + keyword( + arg='memory', + value=Call( + func=Name(id='bytearray', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='code', + value=Name(id='code', ctx=Load())), + keyword( + arg='gas_left', + value=Attribute( + value=Name(id='message', ctx=Load()), + attr='gas', + ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='valid_jump_destinations', + value=Name(id='valid_jump_destinations', ctx=Load())), + keyword( + arg='logs', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='refund_counter', + value=Constant(value=0)), + keyword( + arg='running', + value=Constant(value=True)), + keyword( + arg='message', + value=Name(id='message', ctx=Load())), + keyword( + arg='output', + value=Constant(value=b'')), + keyword( + arg='accounts_to_delete', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='error', + value=Constant(value=None))])), + Try( + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='PRE_COMPILED_CONTRACTS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileStart', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='PRE_COMPILED_CONTRACTS', ctx=Load()), + slice=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='code_address', + ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='PrecompileEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Return( + value=Name(id='evm', ctx=Load()))], + orelse=[]), + While( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[])])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='InvalidOpcode', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load()), + slice=Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Name(id='op', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Subscript( + value=Name(id='op_implementation', ctx=Load()), + slice=Name(id='op', ctx=Load()), + ctx=Load()), + args=[ + Name(id='evm', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpEnd', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='EvmStop', ctx=Load()), + args=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='STOP', + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ExceptionalHalt', ctx=Load()), + name='error', + body=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpException', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='error', + ctx=Store())], + value=Name(id='error', ctx=Load()))])], + orelse=[], + finalbody=[]), + Return( + value=Name(id='evm', ctx=Load()))], + decorator_list=[], + returns=Name(id='Evm', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/interpreter.v b/coq/ethereum/tangerine_whistle/vm/interpreter.v new file mode 100644 index 0000000000..cc25a8e55c --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/interpreter.v @@ -0,0 +1,165 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Interpreter +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +A straightforward interpreter that executes EVM code. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.trace. +Require ethereum.tangerine_whistle.blocks. +Require ethereum.tangerine_whistle.fork_types. +Require ethereum.tangerine_whistle.state. +Require ethereum.tangerine_whistle.vm. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.precompiled_contracts.mapping. +Require ethereum.tangerine_whistle.vm.__init__. +Require ethereum.tangerine_whistle.vm.exceptions. +Require ethereum.tangerine_whistle.vm.instructions. +Require ethereum.tangerine_whistle.vm.runtime. + +Definition process_message_call (message : Message) (env : Environment) : M MessageCallOutput := + (* + If `message.current` is empty then it creates a smart contract + else it executes a call from the `message.caller` to the `message.target`. + + Parameters + ---------- + message : + Transaction specific items. + + env : + External items required for EVM execution. + + Returns + ------- + output : `MessageCallOutput` + Output of the message call + *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "tx_end" [[ + ethereum.trace.TransactionEnd ~(| + (* TODO expression *), + M.get_field ~(| M.get_local ~(| "evm" |), "output" |), + M.get_field ~(| M.get_local ~(| "evm" |), "error" |) + |) in + ]] in + do* [[ ethereum.trace.evm_trace ~(| + M.get_local ~(| "evm" |), + M.get_local ~(| "tx_end" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition process_create_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.tangerine_whistle.vm.Evm` + Items containing execution specific objects. + *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.destroy_storage ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + do* M.assign "evm" [[ + M.get_local ~(| "process_message" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition process_message (message : Message) (env : Environment) : M Evm := + (* + Executes a call to create a smart contract. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: :py:class:`~ethereum.tangerine_whistle.vm.Evm` + Items containing execution specific objects + *) + (* TODO statement *) + do* [[ state.begin_transaction ~(| + M.get_field ~(| env, "state" |) + |) ]] in + do* [[ state.touch_account ~(| + M.get_field ~(| env, "state" |), + M.get_field ~(| message, "current_target" |) + |) ]] in + (* TODO statement *) + do* M.assign "evm" [[ + M.get_local ~(| "execute_code" |) ~(| + message, + env + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition execute_code (message : Message) (env : Environment) : M Evm := + (* + Executes bytecode present in the `message`. + + Parameters + ---------- + message : + Transaction specific items. + env : + External items required for EVM execution. + + Returns + ------- + evm: `ethereum.vm.EVM` + Items containing execution specific objects + *) + do* M.assign "code" [[ + M.get_field ~(| message, "code" |) in + ]] in + do* M.assign "valid_jump_destinations" [[ + runtime.get_valid_jump_destinations ~(| + M.get_local ~(| "code" |) + |) in + ]] in + do* M.assign "evm" [[ + __init__.Evm ~(| + + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/memory.ast b/coq/ethereum/tangerine_whistle/vm/memory.ast new file mode 100644 index 0000000000..9768643646 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/memory.ast @@ -0,0 +1,148 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Memory\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nEVM memory operations.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='right_pad_zero_bytes')], + level=0), + FunctionDef( + name='memory_write', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes to memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n value :\n Data to write to memory.\n ')), + Assign( + targets=[ + Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='memory_read_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='memory', + annotation=Name(id='bytearray', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from memory.\n\n Parameters\n ----------\n memory :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Subscript( + value=Name(id='memory', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()))], + decorator_list=[], + returns=Name(id='bytearray', ctx=Load())), + FunctionDef( + name='buffer_read', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='buffer', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='start_position', + annotation=Name(id='U256', ctx=Load())), + arg( + arg='size', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read bytes from a buffer. Padding with zeros if necessary.\n\n Parameters\n ----------\n buffer :\n Memory contents of the EVM.\n start_position :\n Starting pointer to the memory.\n size :\n Size of the data that needs to be read from `start_position`.\n\n Returns\n -------\n data_bytes :\n Data read from memory.\n ')), + Return( + value=Call( + func=Name(id='right_pad_zero_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='buffer', ctx=Load()), + slice=Slice( + lower=Name(id='start_position', ctx=Load()), + upper=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='start_position', ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]))), + ctx=Load()), + Name(id='size', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/memory.v b/coq/ethereum/tangerine_whistle/vm/memory.v new file mode 100644 index 0000000000..88b516318f --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/memory.v @@ -0,0 +1,76 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Memory +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +EVM memory operations. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.utils.byte. + +Definition memory_write (memory : bytearray) (start_position : U256) (value : Bytes) : M unit := + (* + Writes to memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + value : + Data to write to memory. + *) + (* TODO assignment *) + M.pure tt. + +Definition memory_read_bytes (memory : bytearray) (start_position : U256) (size : U256) : M bytearray := + (* + Read bytes from memory. + + Parameters + ---------- + memory : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. + +Definition buffer_read (buffer : Bytes) (start_position : U256) (size : U256) : M Bytes := + (* + Read bytes from a buffer. Padding with zeros if necessary. + + Parameters + ---------- + buffer : + Memory contents of the EVM. + start_position : + Starting pointer to the memory. + size : + Size of the data that needs to be read from `start_position`. + + Returns + ------- + data_bytes : + Data read from memory. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.ast b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.ast new file mode 100644 index 0000000000..2ac4916772 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.ast @@ -0,0 +1,52 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nAddresses of precompiled contracts and mappings to their\nimplementations.\n')), + ImportFrom( + module='utils.hexadecimal', + names=[ + alias(name='hex_to_address')], + level=3), + Assign( + targets=[ + Name(id='__all__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='ECRECOVER_ADDRESS'), + Constant(value='SHA256_ADDRESS'), + Constant(value='RIPEMD160_ADDRESS'), + Constant(value='IDENTITY_ADDRESS')], + ctx=Load())), + Assign( + targets=[ + Name(id='ECRECOVER_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x01')], + keywords=[])), + Assign( + targets=[ + Name(id='SHA256_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x02')], + keywords=[])), + Assign( + targets=[ + Name(id='RIPEMD160_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x03')], + keywords=[])), + Assign( + targets=[ + Name(id='IDENTITY_ADDRESS', ctx=Store())], + value=Call( + func=Name(id='hex_to_address', ctx=Load()), + args=[ + Constant(value='0x04')], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.v b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.v new file mode 100644 index 0000000000..7d2fa2b4e2 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/__init__.v @@ -0,0 +1,17 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Addresses of precompiled contracts and mappings to their +implementations. +*) + +Require ethereum.tangerine_whistle.utils.hexadecimal. diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.ast b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.ast new file mode 100644 index 0000000000..d52f78e556 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.ast @@ -0,0 +1,306 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the ECRECOVER precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum.crypto.elliptic_curve', + names=[ + alias(name='SECP256K1N'), + alias(name='secp256k1_recover')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_ECRECOVER'), + alias(name='charge_gas')], + level=3), + ImportFrom( + module='vm.memory', + names=[ + alias(name='buffer_read')], + level=3), + FunctionDef( + name='ecrecover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decrypts the address using elliptic curve DSA recovery mechanism and writes\n the address to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='GAS_ECRECOVER', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash_bytes', ctx=Store())], + value=Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='message_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Name(id='message_hash_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=64)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='buffer_read', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=96)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=28)], + keywords=[])])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='r', ctx=Load())]), + Compare( + left=Name(id='r', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + ops=[ + GtE()], + comparators=[ + Name(id='s', ctx=Load())]), + Compare( + left=Name(id='s', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='SECP256K1N', ctx=Load())])]), + body=[ + Return()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='public_key', ctx=Store())], + value=Call( + func=Name(id='secp256k1_recover', ctx=Load()), + args=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + BinOp( + left=Name(id='v', ctx=Load()), + op=Sub(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[])), + Name(id='message_hash', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Return()])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Subscript( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Name(id='public_key', ctx=Load())], + keywords=[]), + slice=Slice( + lower=Constant(value=12), + upper=Constant(value=32)), + ctx=Load())), + Assign( + targets=[ + Name(id='padded_address', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_address', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.v b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.v new file mode 100644 index 0000000000..054bb8ec41 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ecrecover.v @@ -0,0 +1,110 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) ECRECOVER PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the ECRECOVER precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.crypto.elliptic_curve. +Require ethereum.crypto.hash. +Require ethereum.utils.byte. +Require ethereum.tangerine_whistle.vm. +Require ethereum.tangerine_whistle.vm.gas. +Require ethereum.tangerine_whistle.vm.memory. + +Definition ecrecover (evm : Evm) : M unit := + (* + Decrypts the address using elliptic curve DSA recovery mechanism and writes + the address to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + vm.gas.GAS_ECRECOVER + |) ]] in + do* M.assign "message_hash_bytes" [[ + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 0 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) in + ]] in + do* M.assign "message_hash" [[ + ethereum.crypto.hash.Hash32 ~(| + M.get_local ~(| "message_hash_bytes" |) + |) in + ]] in + do* M.assign "v" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 32 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "r" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 64 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + do* M.assign "s" [[ + M.get_field ~(| ethereum_types.numeric.U256, "from_be_bytes" |) ~(| + vm.memory.buffer_read ~(| + M.get_local ~(| "data" |), + ethereum_types.numeric.U256 ~(| + 96 + |), + ethereum_types.numeric.U256 ~(| + 32 + |) + |) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* M.assign "address" [[ + (* TODO expression *) in + ]] in + do* M.assign "padded_address" [[ + ethereum.utils.byte.left_pad_zero_bytes ~(| + M.get_local ~(| "address" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.ast b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.ast new file mode 100644 index 0000000000..82683f3890 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.ast @@ -0,0 +1,96 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `IDENTITY` precompiled contract.\n')), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_IDENTITY'), + alias(name='GAS_IDENTITY_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='identity', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the message data to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_IDENTITY', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_IDENTITY_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.v b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.v new file mode 100644 index 0000000000..9d3f2ce866 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/identity.v @@ -0,0 +1,41 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) IDENTITY PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `IDENTITY` precompiled contract. +*) + +Require ethereum_types.numeric. +Require ethereum.utils.numeric. +Require ethereum.tangerine_whistle.vm. +Require ethereum.tangerine_whistle.vm.gas. + +Definition identity (evm : Evm) : M unit := + (* + Writes the message data to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ vm.gas.charge_gas ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.ast b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.ast new file mode 100644 index 0000000000..de162645ff --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.ast @@ -0,0 +1,65 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPrecompiled Contract Addresses\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nMapping of precompiled contracts their implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Callable'), + alias(name='Dict')], + level=0), + ImportFrom( + module='fork_types', + names=[ + alias(name='Address')], + level=3), + ImportFrom( + names=[ + alias(name='ECRECOVER_ADDRESS'), + alias(name='IDENTITY_ADDRESS'), + alias(name='RIPEMD160_ADDRESS'), + alias(name='SHA256_ADDRESS')], + level=1), + ImportFrom( + module='ecrecover', + names=[ + alias(name='ecrecover')], + level=1), + ImportFrom( + module='identity', + names=[ + alias(name='identity')], + level=1), + ImportFrom( + module='ripemd160', + names=[ + alias(name='ripemd160')], + level=1), + ImportFrom( + module='sha256', + names=[ + alias(name='sha256')], + level=1), + AnnAssign( + target=Name(id='PRE_COMPILED_CONTRACTS', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Name(id='Callable', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict( + keys=[ + Name(id='ECRECOVER_ADDRESS', ctx=Load()), + Name(id='SHA256_ADDRESS', ctx=Load()), + Name(id='RIPEMD160_ADDRESS', ctx=Load()), + Name(id='IDENTITY_ADDRESS', ctx=Load())], + values=[ + Name(id='ecrecover', ctx=Load()), + Name(id='sha256', ctx=Load()), + Name(id='ripemd160', ctx=Load()), + Name(id='identity', ctx=Load())]), + simple=1)], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.v b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.v new file mode 100644 index 0000000000..e9204239b8 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/mapping.v @@ -0,0 +1,22 @@ +(* Generated *) +(* +Precompiled Contract Addresses +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Mapping of precompiled contracts their implementations. +*) + +Require typing. +Require ethereum.tangerine_whistle.fork_types. +Require ethereum.tangerine_whistle.vm.precompiled_contracts.__init__. +Require ethereum.tangerine_whistle.vm.precompiled_contracts.ecrecover. +Require ethereum.tangerine_whistle.vm.precompiled_contracts.identity. +Require ethereum.tangerine_whistle.vm.precompiled_contracts.ripemd160. +Require ethereum.tangerine_whistle.vm.precompiled_contracts.sha256. diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.ast b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.ast new file mode 100644 index 0000000000..e84bdc425f --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.ast @@ -0,0 +1,131 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `RIPEMD160` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_RIPEMD160'), + alias(name='GAS_RIPEMD160_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='ripemd160', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the ripemd160 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_RIPEMD160', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_RIPEMD160_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Name(id='hash_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='new', + ctx=Load()), + args=[ + Constant(value='ripemd160'), + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='padded_hash', ctx=Store())], + value=Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Name(id='hash_bytes', ctx=Load()), + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Name(id='padded_hash', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.v b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.v new file mode 100644 index 0000000000..fe2c66bbe6 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/ripemd160.v @@ -0,0 +1,51 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) RIPEMD160 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `RIPEMD160` precompiled contract. +*) + + +Definition ripemd160 (evm : Evm) : M unit := + (* + Writes the ripemd160 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + do* M.assign "hash_bytes" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "hashlib" |), "new" |) ~(| + (* TODO constant *), + M.get_local ~(| "data" |) + |), "digest" |) ~(| + + |) in + ]] in + do* M.assign "padded_hash" [[ + M.get_local ~(| "left_pad_zero_bytes" |) ~(| + M.get_local ~(| "hash_bytes" |), + 32 + |) in + ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.ast b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.ast new file mode 100644 index 0000000000..571c8ce0db --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.ast @@ -0,0 +1,112 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the `SHA256` precompiled contract.\n')), + Import( + names=[ + alias(name='hashlib')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.utils.numeric', + names=[ + alias(name='ceil32')], + level=0), + ImportFrom( + module='vm', + names=[ + alias(name='Evm')], + level=3), + ImportFrom( + module='vm.gas', + names=[ + alias(name='GAS_SHA256'), + alias(name='GAS_SHA256_WORD'), + alias(name='charge_gas')], + level=3), + FunctionDef( + name='sha256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='Evm', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Writes the sha256 hash to output.\n\n Parameters\n ----------\n evm :\n The current EVM frame.\n ')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='data', + ctx=Load())), + Assign( + targets=[ + Name(id='word_count', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='ceil32', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]), + op=FloorDiv(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))), + Expr( + value=Call( + func=Name(id='charge_gas', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + BinOp( + left=Name(id='GAS_SHA256', ctx=Load()), + op=Add(), + right=BinOp( + left=Name(id='GAS_SHA256_WORD', ctx=Load()), + op=Mult(), + right=Name(id='word_count', ctx=Load())))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='hashlib', ctx=Load()), + attr='sha256', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + attr='digest', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.v b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.v new file mode 100644 index 0000000000..3ba3ffe7aa --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/precompiled_contracts/sha256.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) SHA256 PRECOMPILED CONTRACT +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the `SHA256` precompiled contract. +*) + + +Definition sha256 (evm : Evm) : M unit := + (* + Writes the sha256 hash to output. + + Parameters + ---------- + evm : + The current EVM frame. + *) + do* M.assign "data" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "data" |) in + ]] in + do* M.assign "word_count" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_local ~(| "charge_gas" |) ~(| + evm, + (* TODO expression *) + |) ]] in + (* TODO assignment *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/runtime.ast b/coq/ethereum/tangerine_whistle/vm/runtime.ast new file mode 100644 index 0000000000..ccfcafa4b8 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/runtime.ast @@ -0,0 +1,180 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Runtime Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nRuntime related operations used while executing EVM code.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Set')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='Uint'), + alias(name='ulen')], + level=0), + ImportFrom( + module='instructions', + names=[ + alias(name='Ops')], + level=1), + FunctionDef( + name='get_valid_jump_destinations', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='code', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Analyze the evm code to obtain the set of valid jump destinations.\n\n Valid jump destinations are defined as follows:\n * The jump destination is less than the length of the code.\n * The jump destination should have the `JUMPDEST` opcode (0x5B).\n * The jump destination shouldn't be part of the data corresponding to\n `PUSH-N` opcodes.\n\n Note - Jump destinations are 0-indexed.\n\n Parameters\n ----------\n code :\n The EVM code which is to be executed.\n\n Returns\n -------\n valid_jump_destinations: `Set[Uint]`\n The set of valid jump destinations in the code.\n ")), + Assign( + targets=[ + Name(id='valid_jump_destinations', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='pc', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + While( + test=Compare( + left=Name(id='pc', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='ulen', ctx=Load()), + args=[ + Name(id='code', ctx=Load())], + keywords=[])]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='current_opcode', ctx=Store())], + value=Call( + func=Name(id='Ops', ctx=Load()), + args=[ + Subscript( + value=Name(id='code', ctx=Load()), + slice=Name(id='pc', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='current_opcode', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='Ops', ctx=Load()), + attr='JUMPDEST', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='valid_jump_destinations', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='pc', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + LtE(), + LtE()], + comparators=[ + Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH32', + ctx=Load()), + attr='value', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='push_data_size', ctx=Store())], + value=BinOp( + left=BinOp( + left=Attribute( + value=Name(id='current_opcode', ctx=Load()), + attr='value', + ctx=Load()), + op=Sub(), + right=Attribute( + value=Attribute( + value=Name(id='Ops', ctx=Load()), + attr='PUSH1', + ctx=Load()), + attr='value', + ctx=Load())), + op=Add(), + right=Constant(value=1))), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='push_data_size', ctx=Load())], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='pc', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='valid_jump_destinations', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/runtime.v b/coq/ethereum/tangerine_whistle/vm/runtime.v new file mode 100644 index 0000000000..b43bafdb58 --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/runtime.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Runtime Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Runtime related operations used while executing EVM code. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.tangerine_whistle.vm.instructions. + +Definition get_valid_jump_destinations (code : bytes) : M (* TODO type *) := + (* + Analyze the evm code to obtain the set of valid jump destinations. + + Valid jump destinations are defined as follows: + * The jump destination is less than the length of the code. + * The jump destination should have the `JUMPDEST` opcode (0x5B). + * The jump destination shouldn't be part of the data corresponding to + `PUSH-N` opcodes. + + Note - Jump destinations are 0-indexed. + + Parameters + ---------- + code : + The EVM code which is to be executed. + + Returns + ------- + valid_jump_destinations: `Set[Uint]` + The set of valid jump destinations in the code. + *) + do* M.assign "valid_jump_destinations" [[ + M.get_local ~(| "set" |) ~(| + + |) in + ]] in + do* M.assign "pc" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/tangerine_whistle/vm/stack.ast b/coq/ethereum/tangerine_whistle/vm/stack.ast new file mode 100644 index 0000000000..4c5f36c08b --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/stack.ast @@ -0,0 +1,109 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Virtual Machine (EVM) Stack\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nImplementation of the stack operators for the EVM.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='exceptions', + names=[ + alias(name='StackOverflowError'), + alias(name='StackUnderflowError')], + level=1), + FunctionDef( + name='pop', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pops the top item off of `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n Returns\n -------\n value : `U256`\n The top element on the stack.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Raise( + exc=Name(id='StackUnderflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='push', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='stack', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pushes `value` onto `stack`.\n\n Parameters\n ----------\n stack :\n EVM stack.\n\n value :\n Item to be pushed onto `stack`.\n\n ')), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='stack', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=1024)]), + body=[ + Raise( + exc=Name(id='StackOverflowError', ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/tangerine_whistle/vm/stack.v b/coq/ethereum/tangerine_whistle/vm/stack.v new file mode 100644 index 0000000000..88ada3772d --- /dev/null +++ b/coq/ethereum/tangerine_whistle/vm/stack.v @@ -0,0 +1,54 @@ +(* Generated *) +(* +Ethereum Virtual Machine (EVM) Stack +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Implementation of the stack operators for the EVM. +*) + +Require typing. +Require ethereum_types.numeric. +Require ethereum.tangerine_whistle.vm.exceptions. + +Definition pop (stack : (* TODO type *)) : M U256 := + (* + Pops the top item off of `stack`. + + Parameters + ---------- + stack : + EVM stack. + + Returns + ------- + value : `U256` + The top element on the stack. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition push (stack : (* TODO type *)) (value : U256) : M unit := + (* + Pushes `value` onto `stack`. + + Parameters + ---------- + stack : + EVM stack. + + value : + Item to be pushed onto `stack`. + + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/trace.ast b/coq/ethereum/trace.ast new file mode 100644 index 0000000000..043fd66c82 --- /dev/null +++ b/coq/ethereum/trace.ast @@ -0,0 +1,257 @@ +Module( + body=[ + Expr( + value=Constant(value='\nDefines the functions required for creating EVM traces during execution.\n\nA _trace_ is a log of operations that took place during an event or period of\ntime. In the case of an EVM trace, the log is built from a series of\n[`TraceEvent`]s emitted during the execution of a transaction.\n\nNote that this module _does not_ contain a trace implementation. Instead, it\ndefines only the events that can be collected into a trace by some other\npackage. See [`EvmTracer`].\n\nSee [EIP-3155] for more details on EVM traces.\n\n[`EvmTracer`]: ref:ethereum.trace.EvmTracer\n[`TraceEvent`]: ref:ethereum.trace.TraceEvent\n[EIP-3155]: https://eips.ethereum.org/EIPS/eip-3155\n')), + Import( + names=[ + alias(name='enum')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Protocol'), + alias(name='Union')], + level=0), + ClassDef( + name='TransactionStart', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Trace event that is triggered at the start of a transaction.\n '))], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='TransactionEnd', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Trace event that is triggered at the end of a transaction.\n ')), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n Total gas consumed by this transaction.\n ')), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n Return value or revert reason of the outermost frame of execution.\n ')), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n The exception, if any, that caused the transaction to fail.\n\n See [`ethereum.exceptions`] as well as fork-specific modules like\n [`ethereum.frontier.vm.exceptions`][vm] for details.\n\n [`ethereum.exceptions`]: ref:ethereum.exceptions\n [vm]: ref:ethereum.frontier.vm.exceptions\n '))], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='PrecompileStart', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Trace event that is triggered before executing a precompile.\n ')), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='bytes', ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n Precompile that is about to be executed.\n '))], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='PrecompileEnd', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Trace event that is triggered after executing a precompile.\n '))], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='OpStart', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Trace event that is triggered before executing an opcode.\n ')), + AnnAssign( + target=Name(id='op', ctx=Store()), + annotation=Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n Opcode that is about to be executed.\n\n Will be an instance of a fork-specific type like, for example,\n [`ethereum.frontier.vm.instructions.Ops`][ops].\n\n [ops]: ref:ethereum.frontier.vm.instructions.Ops\n '))], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='OpEnd', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Trace event that is triggered after executing an opcode.\n '))], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='OpException', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Trace event that is triggered when an opcode raises an exception.\n ')), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Name(id='Exception', ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n Exception that was raised.\n\n See [`ethereum.exceptions`] as well as fork-specific modules like\n [`ethereum.frontier.vm.exceptions`][vm] for examples of exceptions that\n might be raised.\n\n [`ethereum.exceptions`]: ref:ethereum.exceptions\n [vm]: ref:ethereum.frontier.vm.exceptions\n '))], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='EvmStop', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Trace event that is triggered when the EVM stops.\n ')), + AnnAssign( + target=Name(id='op', ctx=Store()), + annotation=Attribute( + value=Name(id='enum', ctx=Load()), + attr='Enum', + ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n Last opcode executed.\n\n Will be an instance of a fork-specific type like, for example,\n [`ethereum.frontier.vm.instructions.Ops`][ops].\n\n [ops]: ref:ethereum.frontier.vm.instructions.Ops\n '))], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='GasAndRefund', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Trace event that is triggered when gas is deducted.\n ')), + AnnAssign( + target=Name(id='gas_cost', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + Expr( + value=Constant(value='\n Amount of gas charged or refunded.\n '))], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + Assign( + targets=[ + Name(id='TraceEvent', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='TransactionStart', ctx=Load()), + Name(id='TransactionEnd', ctx=Load()), + Name(id='PrecompileStart', ctx=Load()), + Name(id='PrecompileEnd', ctx=Load()), + Name(id='OpStart', ctx=Load()), + Name(id='OpEnd', ctx=Load()), + Name(id='OpException', ctx=Load()), + Name(id='EvmStop', ctx=Load()), + Name(id='GasAndRefund', ctx=Load())], + ctx=Load()), + ctx=Load())), + Expr( + value=Constant(value='\nAll possible types of events that an [`EvmTracer`] is expected to handle.\n\n[`EvmTracer`]: ref:ethereum.trace.EvmTracer\n')), + FunctionDef( + name='discard_evm_trace', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='object', ctx=Load())), + arg( + arg='event', + annotation=Name(id='TraceEvent', ctx=Load())), + arg( + arg='trace_memory', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='trace_stack', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='trace_return_data', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=False), + Constant(value=True), + Constant(value=False)]), + body=[ + Expr( + value=Constant(value='\n An [`EvmTracer`] that discards all events.\n\n [`EvmTracer`]: ref:ethereum.trace.EvmTracer\n '))], + decorator_list=[], + returns=Constant(value=None)), + ClassDef( + name='EvmTracer', + bases=[ + Name(id='Protocol', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n [`Protocol`] that describes tracer functions.\n\n See [`ethereum.trace`] for details about tracing in general, and\n [`__call__`] for more on how to implement a tracer.\n\n [`Protocol`]: https://docs.python.org/3/library/typing.html#typing.Protocol\n [`ethereum.trace`]: ref:ethereum.trace\n [`__call__`]: ref:ethereum.trace.EvmTracer.__call__\n ')), + FunctionDef( + name='__call__', + args=arguments( + posonlyargs=[ + arg(arg='self'), + arg( + arg='evm', + annotation=Name(id='object', ctx=Load())), + arg( + arg='event', + annotation=Name(id='TraceEvent', ctx=Load()))], + args=[ + arg( + arg='trace_memory', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='trace_stack', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='trace_return_data', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=False), + Constant(value=True), + Constant(value=False)]), + body=[ + Expr( + value=Constant(value='\n Call `self` as a function, recording a trace event.\n\n `evm` is the live state of the EVM, and will be a fork-specific type\n like [`ethereum.frontier.vm.Evm`][evm].\n\n `event`, a [`TraceEvent`], is the reason why the tracer was triggered.\n\n `trace_memory` requests a full memory dump in the resulting trace.\n\n `trace_stack` requests the full stack in the resulting trace.\n\n `trace_return_data` requests that return data be included in the\n resulting trace.\n\n See [`discard_evm_trace`] for an example function implementing this\n protocol.\n\n [`discard_evm_trace`]: ref:ethereum.trace.discard_evm_trace\n [evm]: ref:ethereum.frontier.vm.Evm\n [`TraceEvent`]: ref:ethereum.trace.TraceEvent\n '))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + AnnAssign( + target=Name(id='evm_trace', ctx=Store()), + annotation=Name(id='EvmTracer', ctx=Load()), + value=Name(id='discard_evm_trace', ctx=Load()), + simple=1), + Expr( + value=Constant(value='\nActive [`EvmTracer`] that is used for generating traces.\n\n[`EvmTracer`]: ref:ethereum.trace.EvmTracer\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/trace.v b/coq/ethereum/trace.v new file mode 100644 index 0000000000..e5b06c80ab --- /dev/null +++ b/coq/ethereum/trace.v @@ -0,0 +1,27 @@ +(* Generated *) +(* +Defines the functions required for creating EVM traces during execution. + +A _trace_ is a log of operations that took place during an event or period of +time. In the case of an EVM trace, the log is built from a series of +[`TraceEvent`]s emitted during the execution of a transaction. + +Note that this module _does not_ contain a trace implementation. Instead, it +defines only the events that can be collected into a trace by some other +package. See [`EvmTracer`]. + +See [EIP-3155] for more details on EVM traces. + +[`EvmTracer`]: ref:ethereum.trace.EvmTracer +[`TraceEvent`]: ref:ethereum.trace.TraceEvent +[EIP-3155]: https://eips.ethereum.org/EIPS/eip-3155 +*) + + +Definition discard_evm_trace (evm : object) (event : TraceEvent) (trace_memory : bool) (trace_stack : bool) (trace_return_data : bool) : M unit := + (* + An [`EvmTracer`] that discards all events. + + [`EvmTracer`]: ref:ethereum.trace.EvmTracer + *) + M.pure tt. diff --git a/coq/ethereum/utils/__init__.ast b/coq/ethereum/utils/__init__.ast new file mode 100644 index 0000000000..a9d0c8fa17 --- /dev/null +++ b/coq/ethereum/utils/__init__.ast @@ -0,0 +1,73 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility functions used in this specification.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='fields')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Any')], + level=0), + FunctionDef( + name='has_field', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='class_', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='name', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns `True` if `class_` has a field with the given `name`.\n ')), + Try( + body=[ + Assign( + targets=[ + Name(id='all_fields', ctx=Store())], + value=Call( + func=Name(id='fields', ctx=Load()), + args=[ + Name(id='class_', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='TypeError', ctx=Load()), + body=[ + Return( + value=Constant(value=False))])], + orelse=[], + finalbody=[]), + Return( + value=Call( + func=Name(id='any', ctx=Load()), + args=[ + GeneratorExp( + elt=Compare( + left=Attribute( + value=Name(id='x', ctx=Load()), + attr='name', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='name', ctx=Load())]), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Name(id='all_fields', ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/utils/__init__.v b/coq/ethereum/utils/__init__.v new file mode 100644 index 0000000000..9b0eb36c08 --- /dev/null +++ b/coq/ethereum/utils/__init__.v @@ -0,0 +1,15 @@ +(* Generated *) +(* +Utility functions used in this specification. +*) + +Require dataclasses. +Require typing. + +Definition has_field (class_ : Any) (name : str) : M bool := + (* + Returns `True` if `class_` has a field with the given `name`. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/utils/byte.ast b/coq/ethereum/utils/byte.ast new file mode 100644 index 0000000000..3211916cd1 --- /dev/null +++ b/coq/ethereum/utils/byte.ast @@ -0,0 +1,103 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Byte Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nByte specific utility functions used in this specification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='FixedUnsigned'), + alias(name='Uint')], + level=0), + FunctionDef( + name='left_pad_zero_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='size', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='int', ctx=Load()), + Name(id='FixedUnsigned', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Left pad zeroes to `value` if its length is less than the given `size`.\n\n Parameters\n ----------\n value :\n The byte string that needs to be padded.\n size :\n The number of bytes that need that need to be padded.\n\n Returns\n -------\n left_padded_value: `ethereum.base_types.Bytes`\n left padded byte string of given `size`.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='rjust', + ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]), + Constant(value=b'\x00')], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='right_pad_zero_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='size', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='int', ctx=Load()), + Name(id='FixedUnsigned', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Right pad zeroes to `value` if its length is less than the given `size`.\n\n Parameters\n ----------\n value :\n The byte string that needs to be padded.\n size :\n The number of bytes that need that need to be padded.\n\n Returns\n -------\n right_padded_value: `ethereum.base_types.Bytes`\n right padded byte string of given `size`.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='ljust', + ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='size', ctx=Load())], + keywords=[]), + Constant(value=b'\x00')], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/utils/byte.v b/coq/ethereum/utils/byte.v new file mode 100644 index 0000000000..f0b8f2d86d --- /dev/null +++ b/coq/ethereum/utils/byte.v @@ -0,0 +1,56 @@ +(* Generated *) +(* +Utility Functions For Byte Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Byte specific utility functions used in this specification. +*) + +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. + +Definition left_pad_zero_bytes (value : Bytes) (size : (* TODO type *)) : M Bytes := + (* + Left pad zeroes to `value` if its length is less than the given `size`. + + Parameters + ---------- + value : + The byte string that needs to be padded. + size : + The number of bytes that need that need to be padded. + + Returns + ------- + left_padded_value: `ethereum.base_types.Bytes` + left padded byte string of given `size`. + *) + (* TODO statement *) + M.pure tt. + +Definition right_pad_zero_bytes (value : Bytes) (size : (* TODO type *)) : M Bytes := + (* + Right pad zeroes to `value` if its length is less than the given `size`. + + Parameters + ---------- + value : + The byte string that needs to be padded. + size : + The number of bytes that need that need to be padded. + + Returns + ------- + right_padded_value: `ethereum.base_types.Bytes` + right padded byte string of given `size`. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/utils/hexadecimal.ast b/coq/ethereum/utils/hexadecimal.ast new file mode 100644 index 0000000000..193b5f9d7c --- /dev/null +++ b/coq/ethereum/utils/hexadecimal.ast @@ -0,0 +1,406 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Hexadecimal Strings\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nHexadecimal strings specific utility functions used in this specification.\n')), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes20'), + alias(name='Bytes32'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + FunctionDef( + name='has_hex_prefix', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if a hex string starts with hex prefix (0x).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be checked for presence of prefix.\n\n Returns\n -------\n has_prefix : `bool`\n Boolean indicating whether the hex string has 0x prefix.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='hex_string', ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Constant(value='0x')], + keywords=[]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='remove_hex_prefix', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Remove 0x prefix from a hex string if present. This function returns the\n passed hex string if it isn't prefixed with 0x.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string whose prefix is to be removed.\n\n Returns\n -------\n modified_hex_string : `str`\n The hexadecimal string with the 0x prefix removed if present.\n ")), + If( + test=Call( + func=Name(id='has_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Subscript( + value=Name(id='hex_string', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='len', ctx=Load()), + args=[ + Constant(value='0x')], + keywords=[])), + ctx=Load()))], + orelse=[]), + Return( + value=Name(id='hex_string', ctx=Load()))], + decorator_list=[], + returns=Name(id='str', ctx=Load())), + FunctionDef( + name='hex_to_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to bytes.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to bytes.\n\n Returns\n -------\n byte_stream : `bytes`\n Byte stream corresponding to the given hexadecimal string.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='hex_to_bytes8', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to 8 bytes.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to 8 bytes.\n\n Returns\n -------\n 8_byte_stream : `Bytes8`\n 8-byte stream corresponding to the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bytes8', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=16), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes8', ctx=Load())), + FunctionDef( + name='hex_to_bytes20', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to 20 bytes.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to 20 bytes.\n\n Returns\n -------\n 20_byte_stream : `Bytes20`\n 20-byte stream corresponding to the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bytes20', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=20), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes20', ctx=Load())), + FunctionDef( + name='hex_to_bytes32', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to 32 bytes.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to 32 bytes.\n\n Returns\n -------\n 32_byte_stream : `Bytes32`\n 32-byte stream corresponding to the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bytes32', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=64), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes32', ctx=Load())), + FunctionDef( + name='hex_to_bytes256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to 256 bytes.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to 256 bytes.\n\n Returns\n -------\n 256_byte_stream : `Bytes256`\n 256-byte stream corresponding to the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Bytes256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + attr='rjust', + ctx=Load()), + args=[ + Constant(value=512), + Constant(value='0')], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes256', ctx=Load())), + FunctionDef( + name='hex_to_hash', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to hash32 (32 bytes).\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to hash32.\n\n Returns\n -------\n hash : `Hash32`\n 32-byte stream obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Hash32', ctx=Load())), + FunctionDef( + name='hex_to_uint', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to Uint.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to Uint.\n\n Returns\n -------\n converted : `Uint`\n The unsigned integer obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + Constant(value=16)], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='hex_to_u64', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to U64.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to U256.\n\n Returns\n -------\n converted : `U64`\n The U64 integer obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='U64', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + Constant(value=16)], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='U64', ctx=Load())), + FunctionDef( + name='hex_to_u256', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='hex_string', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert hex string to U256.\n\n Parameters\n ----------\n hex_string :\n The hexadecimal string to be converted to U256.\n\n Returns\n -------\n converted : `U256`\n The U256 integer obtained from the given hexadecimal string.\n ')), + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Call( + func=Name(id='remove_hex_prefix', ctx=Load()), + args=[ + Name(id='hex_string', ctx=Load())], + keywords=[]), + Constant(value=16)], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/utils/hexadecimal.v b/coq/ethereum/utils/hexadecimal.v new file mode 100644 index 0000000000..867a45520c --- /dev/null +++ b/coq/ethereum/utils/hexadecimal.v @@ -0,0 +1,207 @@ +(* Generated *) +(* +Utility Functions For Hexadecimal Strings +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Hexadecimal strings specific utility functions used in this specification. +*) + +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum.crypto.hash. + +Definition has_hex_prefix (hex_string : str) : M bool := + (* + Check if a hex string starts with hex prefix (0x). + + Parameters + ---------- + hex_string : + The hexadecimal string to be checked for presence of prefix. + + Returns + ------- + has_prefix : `bool` + Boolean indicating whether the hex string has 0x prefix. + *) + (* TODO statement *) + M.pure tt. + +Definition remove_hex_prefix (hex_string : str) : M str := + (* + Remove 0x prefix from a hex string if present. This function returns the + passed hex string if it isn't prefixed with 0x. + + Parameters + ---------- + hex_string : + The hexadecimal string whose prefix is to be removed. + + Returns + ------- + modified_hex_string : `str` + The hexadecimal string with the 0x prefix removed if present. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bytes (hex_string : str) : M Bytes := + (* + Convert hex string to bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to bytes. + + Returns + ------- + byte_stream : `bytes` + Byte stream corresponding to the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bytes8 (hex_string : str) : M Bytes8 := + (* + Convert hex string to 8 bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to 8 bytes. + + Returns + ------- + 8_byte_stream : `Bytes8` + 8-byte stream corresponding to the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bytes20 (hex_string : str) : M Bytes20 := + (* + Convert hex string to 20 bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to 20 bytes. + + Returns + ------- + 20_byte_stream : `Bytes20` + 20-byte stream corresponding to the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bytes32 (hex_string : str) : M Bytes32 := + (* + Convert hex string to 32 bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to 32 bytes. + + Returns + ------- + 32_byte_stream : `Bytes32` + 32-byte stream corresponding to the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_bytes256 (hex_string : str) : M Bytes256 := + (* + Convert hex string to 256 bytes. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to 256 bytes. + + Returns + ------- + 256_byte_stream : `Bytes256` + 256-byte stream corresponding to the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_hash (hex_string : str) : M Hash32 := + (* + Convert hex string to hash32 (32 bytes). + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to hash32. + + Returns + ------- + hash : `Hash32` + 32-byte stream obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_uint (hex_string : str) : M Uint := + (* + Convert hex string to Uint. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to Uint. + + Returns + ------- + converted : `Uint` + The unsigned integer obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_u64 (hex_string : str) : M U64 := + (* + Convert hex string to U64. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to U256. + + Returns + ------- + converted : `U64` + The U64 integer obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. + +Definition hex_to_u256 (hex_string : str) : M U256 := + (* + Convert hex string to U256. + + Parameters + ---------- + hex_string : + The hexadecimal string to be converted to U256. + + Returns + ------- + converted : `U256` + The U256 integer obtained from the given hexadecimal string. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/utils/numeric.ast b/coq/ethereum/utils/numeric.ast new file mode 100644 index 0000000000..cccbcf0920 --- /dev/null +++ b/coq/ethereum/utils/numeric.ast @@ -0,0 +1,421 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtility Functions For Numeric Operations\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nNumeric operations specific utility functions used in this specification.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Sequence'), + alias(name='SupportsInt'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U32'), + alias(name='Uint')], + level=0), + FunctionDef( + name='get_sign', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Determines the sign of a number.\n\n Parameters\n ----------\n value :\n The value whose sign is to be determined.\n\n Returns\n -------\n sign : `int`\n The sign of the number (-1 or 0 or 1).\n The return value is based on math signum function.\n ')), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=UnaryOp( + op=USub(), + operand=Constant(value=1)))], + orelse=[ + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=0))], + orelse=[ + Return( + value=Constant(value=1))])])], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='ceil32', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Converts a unsigned integer to the next closest multiple of 32.\n\n Parameters\n ----------\n value :\n The value whose ceil32 is to be calculated.\n\n Returns\n -------\n ceil32 : `ethereum.base_types.U256`\n The same value if it's a perfect multiple of 32\n else it returns the smallest multiple of 32\n that is greater than `value`.\n ")), + Assign( + targets=[ + Name(id='ceiling', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[])), + Assign( + targets=[ + Name(id='remainder', ctx=Store())], + value=BinOp( + left=Name(id='value', ctx=Load()), + op=Mod(), + right=Name(id='ceiling', ctx=Load()))), + If( + test=Compare( + left=Name(id='remainder', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + Return( + value=Name(id='value', ctx=Load()))], + orelse=[ + Return( + value=BinOp( + left=BinOp( + left=Name(id='value', ctx=Load()), + op=Add(), + right=Name(id='ceiling', ctx=Load())), + op=Sub(), + right=Name(id='remainder', ctx=Load())))])], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='is_prime', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='number', + annotation=Name(id='SupportsInt', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks if `number` is a prime number.\n\n Parameters\n ----------\n number :\n The number to check for primality.\n\n Returns\n -------\n is_number_prime : `bool`\n Boolean indicating if `number` is prime or not.\n ')), + Assign( + targets=[ + Name(id='number', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='number', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='number', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Constant(value=1)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + For( + target=Name(id='x', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=2), + BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + BinOp( + left=Name(id='number', ctx=Load()), + op=Pow(), + right=Constant(value=0.5))], + keywords=[]), + op=Add(), + right=Constant(value=1))], + keywords=[]), + body=[ + If( + test=Compare( + left=BinOp( + left=Name(id='number', ctx=Load()), + op=Mod(), + right=Name(id='x', ctx=Load())), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[])], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='le_bytes_to_uint32_sequence', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='data', + annotation=Name(id='bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Convert little endian byte stream `data` to a little endian U32\n sequence i.e., the first U32 number of the sequence is the least\n significant U32 number.\n\n Parameters\n ----------\n data :\n The byte stream (little endian) which is to be converted to a U32\n stream.\n\n Returns\n -------\n uint32_sequence : `Tuple[U32, ...]`\n Sequence of U32 numbers obtained from the little endian byte\n stream.\n ')), + Assign( + targets=[ + Name(id='sequence', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]), + Constant(value=4)], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='sequence', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='U32', ctx=Load()), + attr='from_le_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Slice( + lower=Name(id='i', ctx=Load()), + upper=BinOp( + left=Name(id='i', ctx=Load()), + op=Add(), + right=Constant(value=4))), + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='sequence', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U32', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='le_uint32_sequence_to_bytes', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sequence', + annotation=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='U32', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Obtain little endian byte stream from a little endian U32 sequence\n i.e., the first U32 number of the sequence is the least significant\n U32 number.\n\n Note - In this conversion, the most significant byte (byte at the end of\n the little endian stream) may have leading zeroes. This function doesn't\n take care of removing these leading zeroes as shown in below example.\n\n >>> le_uint32_sequence_to_bytes([U32(8)])\n b'\\x08\\x00\\x00\\x00'\n\n\n Parameters\n ----------\n sequence :\n The U32 stream (little endian) which is to be converted to a\n little endian byte stream.\n\n Returns\n -------\n result : `bytes`\n The byte stream obtained from the little endian U32 stream.\n ")), + Assign( + targets=[ + Name(id='result_bytes', ctx=Store())], + value=Constant(value=b'')), + For( + target=Name(id='item', ctx=Store()), + iter=Name(id='sequence', ctx=Load()), + body=[ + AugAssign( + target=Name(id='result_bytes', ctx=Store()), + op=Add(), + value=Call( + func=Attribute( + value=Name(id='item', ctx=Load()), + attr='to_le_bytes4', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='result_bytes', ctx=Load()))], + decorator_list=[], + returns=Name(id='bytes', ctx=Load())), + FunctionDef( + name='le_uint32_sequence_to_uint', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='sequence', + annotation=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='U32', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Obtain Uint from a U32 sequence assuming that this sequence is little\n endian i.e., the first U32 number of the sequence is the least\n significant U32 number.\n\n Parameters\n ----------\n sequence :\n The U32 stream (little endian) which is to be converted to a Uint.\n\n Returns\n -------\n value : `Uint`\n The Uint number obtained from the conversion of the little endian\n U32 stream.\n ')), + Assign( + targets=[ + Name(id='sequence_as_bytes', ctx=Store())], + value=Call( + func=Name(id='le_uint32_sequence_to_bytes', ctx=Load()), + args=[ + Name(id='sequence', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Attribute( + value=Name(id='Uint', ctx=Load()), + attr='from_le_bytes', + ctx=Load()), + args=[ + Name(id='sequence_as_bytes', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='taylor_exponential', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='factor', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='numerator', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='denominator', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Approximates factor * e ** (numerator / denominator) using\n Taylor expansion.\n\n Parameters\n ----------\n factor :\n The factor.\n numerator :\n The numerator of the exponential.\n denominator :\n The denominator of the exponential.\n\n Returns\n -------\n output : `ethereum.base_types.Uint`\n The approximation of factor * e ** (numerator / denominator).\n\n ')), + Assign( + targets=[ + Name(id='i', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Name(id='numerator_accumulated', ctx=Store())], + value=BinOp( + left=Name(id='factor', ctx=Load()), + op=Mult(), + right=Name(id='denominator', ctx=Load()))), + While( + test=Compare( + left=Name(id='numerator_accumulated', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])]), + body=[ + AugAssign( + target=Name(id='output', ctx=Store()), + op=Add(), + value=Name(id='numerator_accumulated', ctx=Load())), + Assign( + targets=[ + Name(id='numerator_accumulated', ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='numerator_accumulated', ctx=Load()), + op=Mult(), + right=Name(id='numerator', ctx=Load())), + op=FloorDiv(), + right=BinOp( + left=Name(id='denominator', ctx=Load()), + op=Mult(), + right=Name(id='i', ctx=Load())))), + AugAssign( + target=Name(id='i', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + Return( + value=BinOp( + left=Name(id='output', ctx=Load()), + op=FloorDiv(), + right=Name(id='denominator', ctx=Load())))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/utils/numeric.v b/coq/ethereum/utils/numeric.v new file mode 100644 index 0000000000..68a18d2cb1 --- /dev/null +++ b/coq/ethereum/utils/numeric.v @@ -0,0 +1,205 @@ +(* Generated *) +(* +Utility Functions For Numeric Operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Numeric operations specific utility functions used in this specification. +*) + +Require typing. +Require ethereum_types.numeric. + +Definition get_sign (value : int) : M int := + (* + Determines the sign of a number. + + Parameters + ---------- + value : + The value whose sign is to be determined. + + Returns + ------- + sign : `int` + The sign of the number (-1 or 0 or 1). + The return value is based on math signum function. + *) + (* TODO statement *) + M.pure tt. + +Definition ceil32 (value : Uint) : M Uint := + (* + Converts a unsigned integer to the next closest multiple of 32. + + Parameters + ---------- + value : + The value whose ceil32 is to be calculated. + + Returns + ------- + ceil32 : `ethereum.base_types.U256` + The same value if it's a perfect multiple of 32 + else it returns the smallest multiple of 32 + that is greater than `value`. + *) + do* M.assign "ceiling" [[ + ethereum_types.numeric.Uint ~(| + 32 + |) in + ]] in + do* M.assign "remainder" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition is_prime (number : SupportsInt) : M bool := + (* + Checks if `number` is a prime number. + + Parameters + ---------- + number : + The number to check for primality. + + Returns + ------- + is_number_prime : `bool` + Boolean indicating if `number` is prime or not. + *) + do* M.assign "number" [[ + M.get_local ~(| "int" |) ~(| + number + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition le_bytes_to_uint32_sequence (data : bytes) : M (* TODO type *) := + (* + Convert little endian byte stream `data` to a little endian U32 + sequence i.e., the first U32 number of the sequence is the least + significant U32 number. + + Parameters + ---------- + data : + The byte stream (little endian) which is to be converted to a U32 + stream. + + Returns + ------- + uint32_sequence : `Tuple[U32, ...]` + Sequence of U32 numbers obtained from the little endian byte + stream. + *) + do* M.assign "sequence" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition le_uint32_sequence_to_bytes (sequence : (* TODO type *)) : M bytes := + (* + Obtain little endian byte stream from a little endian U32 sequence + i.e., the first U32 number of the sequence is the least significant + U32 number. + + Note - In this conversion, the most significant byte (byte at the end of + the little endian stream) may have leading zeroes. This function doesn't + take care of removing these leading zeroes as shown in below example. + + >>> le_uint32_sequence_to_bytes([U32(8)]) + b'\x08\x00\x00\x00' + + + Parameters + ---------- + sequence : + The U32 stream (little endian) which is to be converted to a + little endian byte stream. + + Returns + ------- + result : `bytes` + The byte stream obtained from the little endian U32 stream. + *) + do* M.assign "result_bytes" [[ + (* TODO constant *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition le_uint32_sequence_to_uint (sequence : (* TODO type *)) : M Uint := + (* + Obtain Uint from a U32 sequence assuming that this sequence is little + endian i.e., the first U32 number of the sequence is the least + significant U32 number. + + Parameters + ---------- + sequence : + The U32 stream (little endian) which is to be converted to a Uint. + + Returns + ------- + value : `Uint` + The Uint number obtained from the conversion of the little endian + U32 stream. + *) + do* M.assign "sequence_as_bytes" [[ + M.get_local ~(| "le_uint32_sequence_to_bytes" |) ~(| + sequence + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition taylor_exponential (factor : Uint) (numerator : Uint) (denominator : Uint) : M Uint := + (* + Approximates factor * e ** (numerator / denominator) using + Taylor expansion. + + Parameters + ---------- + factor : + The factor. + numerator : + The numerator of the exponential. + denominator : + The denominator of the exponential. + + Returns + ------- + output : `ethereum.base_types.Uint` + The approximation of factor * e ** (numerator / denominator). + + *) + do* M.assign "i" [[ + ethereum_types.numeric.Uint ~(| + 1 + |) in + ]] in + do* M.assign "output" [[ + ethereum_types.numeric.Uint ~(| + 0 + |) in + ]] in + do* M.assign "numerator_accumulated" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum/utils/safe_arithmetic.ast b/coq/ethereum/utils/safe_arithmetic.ast new file mode 100644 index 0000000000..00b4879588 --- /dev/null +++ b/coq/ethereum/utils/safe_arithmetic.ast @@ -0,0 +1,175 @@ +Module( + body=[ + Expr( + value=Constant(value='\nSafe Arithmetic for U256 Integer Type\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nSafe arithmetic utility functions for U256 integer type.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Type'), + alias(name='Union')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + FunctionDef( + name='u256_safe_add', + args=arguments( + posonlyargs=[], + args=[], + vararg=arg( + arg='numbers', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load()), + ctx=Load())), + kwonlyargs=[ + arg( + arg='exception_type', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='BaseException', ctx=Load()), + ctx=Load()), + ctx=Load()))], + kw_defaults=[ + Constant(value=None)], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds together the given sequence of numbers. If the total sum of the\n numbers exceeds `U256.MAX_VALUE` then an exception is raised.\n If `exception_type` = None then the exception raised defaults to the one\n raised by `U256` when `U256.value > U256.MAX_VALUE`\n else `exception_type` is raised.\n\n Parameters\n ----------\n numbers :\n The sequence of numbers that need to be added together.\n\n exception_type:\n The exception that needs to be raised if the sum of the `numbers`\n exceeds `U256.MAX_VALUE`.\n\n Returns\n -------\n result : `ethereum.base_types.U256`\n The sum of the given sequence of numbers if the total is less than\n `U256.MAX_VALUE` else an exception is raised.\n If `exception_type` = None then the exception raised defaults to the\n one raised by `U256` when `U256.value > U256.MAX_VALUE`\n else `exception_type` is raised.\n ')), + Try( + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='sum', ctx=Load()), + args=[ + GeneratorExp( + elt=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='n', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='n', ctx=Store()), + iter=Name(id='numbers', ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + name='e', + body=[ + If( + test=Name(id='exception_type', ctx=Load()), + body=[ + Raise( + exc=Name(id='exception_type', ctx=Load()), + cause=Name(id='e', ctx=Load()))], + orelse=[ + Raise( + exc=Name(id='e', ctx=Load()))])])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='u256_safe_multiply', + args=arguments( + posonlyargs=[], + args=[], + vararg=arg( + arg='numbers', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load()), + ctx=Load())), + kwonlyargs=[ + arg( + arg='exception_type', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='BaseException', ctx=Load()), + ctx=Load()), + ctx=Load()))], + kw_defaults=[ + Constant(value=None)], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Multiplies together the given sequence of numbers. If the net product of\n the numbers exceeds `U256.MAX_VALUE` then an exception is raised.\n If `exception_type` = None then the exception raised defaults to the one\n raised by `U256` when `U256.value > U256.MAX_VALUE` else\n `exception_type` is raised.\n\n Parameters\n ----------\n numbers :\n The sequence of numbers that need to be multiplies together.\n\n exception_type:\n The exception that needs to be raised if the sum of the `numbers`\n exceeds `U256.MAX_VALUE`.\n\n Returns\n -------\n result : `ethereum.base_types.U256`\n The multiplication product of the given sequence of numbers if the\n net product is less than `U256.MAX_VALUE` else an exception is raised.\n If `exception_type` = None then the exception raised defaults to the\n one raised by `U256` when `U256.value > U256.MAX_VALUE`\n else `exception_type` is raised.\n ')), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Subscript( + value=Name(id='numbers', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[])), + Try( + body=[ + For( + target=Name(id='number', ctx=Store()), + iter=Subscript( + value=Name(id='numbers', ctx=Load()), + slice=Slice( + lower=Constant(value=1)), + ctx=Load()), + body=[ + AugAssign( + target=Name(id='result', ctx=Store()), + op=Mult(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='number', ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Name(id='result', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + name='e', + body=[ + If( + test=Name(id='exception_type', ctx=Load()), + body=[ + Raise( + exc=Name(id='exception_type', ctx=Load()), + cause=Name(id='e', ctx=Load()))], + orelse=[ + Raise( + exc=Name(id='e', ctx=Load()))])])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='U256', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum/utils/safe_arithmetic.v b/coq/ethereum/utils/safe_arithmetic.v new file mode 100644 index 0000000000..b0098f6c2b --- /dev/null +++ b/coq/ethereum/utils/safe_arithmetic.v @@ -0,0 +1,80 @@ +(* Generated *) +(* +Safe Arithmetic for U256 Integer Type +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Safe arithmetic utility functions for U256 integer type. +*) + +Require typing. +Require ethereum_types.numeric. + +Definition u256_safe_add : M U256 := + (* + Adds together the given sequence of numbers. If the total sum of the + numbers exceeds `U256.MAX_VALUE` then an exception is raised. + If `exception_type` = None then the exception raised defaults to the one + raised by `U256` when `U256.value > U256.MAX_VALUE` + else `exception_type` is raised. + + Parameters + ---------- + numbers : + The sequence of numbers that need to be added together. + + exception_type: + The exception that needs to be raised if the sum of the `numbers` + exceeds `U256.MAX_VALUE`. + + Returns + ------- + result : `ethereum.base_types.U256` + The sum of the given sequence of numbers if the total is less than + `U256.MAX_VALUE` else an exception is raised. + If `exception_type` = None then the exception raised defaults to the + one raised by `U256` when `U256.value > U256.MAX_VALUE` + else `exception_type` is raised. + *) + (* TODO statement *) + M.pure tt. + +Definition u256_safe_multiply : M U256 := + (* + Multiplies together the given sequence of numbers. If the net product of + the numbers exceeds `U256.MAX_VALUE` then an exception is raised. + If `exception_type` = None then the exception raised defaults to the one + raised by `U256` when `U256.value > U256.MAX_VALUE` else + `exception_type` is raised. + + Parameters + ---------- + numbers : + The sequence of numbers that need to be multiplies together. + + exception_type: + The exception that needs to be raised if the sum of the `numbers` + exceeds `U256.MAX_VALUE`. + + Returns + ------- + result : `ethereum.base_types.U256` + The multiplication product of the given sequence of numbers if the + net product is less than `U256.MAX_VALUE` else an exception is raised. + If `exception_type` = None then the exception raised defaults to the + one raised by `U256` when `U256.value > U256.MAX_VALUE` + else `exception_type` is raised. + *) + do* M.assign "result" [[ + ethereum_types.numeric.Uint ~(| + (* TODO expression *) + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum_optimized/__init__.ast b/coq/ethereum_optimized/__init__.ast new file mode 100644 index 0000000000..442883b037 --- /dev/null +++ b/coq/ethereum_optimized/__init__.ast @@ -0,0 +1,250 @@ +Module( + body=[ + Expr( + value=Constant(value='\nOptimized Implementations\n^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis module contains alternative implementations of routines in the spec that\nhave been optimized for speed rather than clarity.\n\nThey can be monkey patched in during start up by calling the `monkey_patch()`\nfunction. This must be done before those modules are imported anywhere.\n')), + ImportFrom( + module='importlib', + names=[ + alias(name='import_module')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Any'), + alias(name='Optional'), + alias(name='cast')], + level=0), + ImportFrom( + module='ethereum_spec_tools.forks', + names=[ + alias(name='Hardfork')], + level=0), + ImportFrom( + module='fork', + names=[ + alias(name='get_optimized_pow_patches')], + level=1), + ImportFrom( + module='state_db', + names=[ + alias(name='get_optimized_state_patches')], + level=1), + FunctionDef( + name='monkey_patch_optimized_state_db', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='fork_name', + annotation=Name(id='str', ctx=Load())), + arg( + arg='state_path', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Replace the state interface with one that supports high performance\n updates and storing state in a database.\n\n This function must be called before the state interface is imported\n anywhere.\n ')), + Assign( + targets=[ + Name(id='slow_state', ctx=Store())], + value=Call( + func=Name(id='cast', ctx=Load()), + args=[ + Name(id='Any', ctx=Load()), + Call( + func=Name(id='import_module', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value='ethereum.'), + op=Add(), + right=Name(id='fork_name', ctx=Load())), + op=Add(), + right=Constant(value='.state'))], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='optimized_state_db_patches', ctx=Store())], + value=Call( + func=Name(id='get_optimized_state_patches', ctx=Load()), + args=[ + Name(id='fork_name', ctx=Load())], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='name', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='optimized_state_db_patches', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='setattr', ctx=Load()), + args=[ + Name(id='slow_state', ctx=Load()), + Name(id='name', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='state_path', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Attribute( + value=Attribute( + value=Name(id='slow_state', ctx=Load()), + attr='State', + ctx=Load()), + attr='default_path', + ctx=Store())], + value=Name(id='state_path', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='monkey_patch_optimized_spec', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='fork_name', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Replace the ethash implementation with one that supports higher\n performance.\n\n This function must be called before the spec interface is imported\n anywhere.\n ')), + Assign( + targets=[ + Name(id='slow_spec', ctx=Store())], + value=Call( + func=Name(id='import_module', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value='ethereum.'), + op=Add(), + right=Name(id='fork_name', ctx=Load())), + op=Add(), + right=Constant(value='.fork'))], + keywords=[])), + Assign( + targets=[ + Name(id='optimized_pow_patches', ctx=Store())], + value=Call( + func=Name(id='get_optimized_pow_patches', ctx=Load()), + args=[ + Name(id='fork_name', ctx=Load())], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='name', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='optimized_pow_patches', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='setattr', ctx=Load()), + args=[ + Name(id='slow_spec', ctx=Load()), + Name(id='name', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='monkey_patch', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state_path', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Apply all monkey patches to the specification.\n ')), + Assign( + targets=[ + Name(id='forks', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Hardfork', ctx=Load()), + attr='discover', + ctx=Load()), + args=[], + keywords=[])), + For( + target=Name(id='fork', ctx=Store()), + iter=Name(id='forks', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='monkey_patch_optimized_state_db', ctx=Load()), + args=[ + Attribute( + value=Name(id='fork', ctx=Load()), + attr='short_name', + ctx=Load()), + Name(id='state_path', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='fork', ctx=Load()), + attr='consensus', + ctx=Load()), + attr='is_pow', + ctx=Load()), + args=[], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='monkey_patch_optimized_spec', ctx=Load()), + args=[ + Attribute( + value=Name(id='fork', ctx=Load()), + attr='short_name', + ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_optimized/__init__.v b/coq/ethereum_optimized/__init__.v new file mode 100644 index 0000000000..1bf87aa799 --- /dev/null +++ b/coq/ethereum_optimized/__init__.v @@ -0,0 +1,82 @@ +(* Generated *) +(* +Optimized Implementations +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This module contains alternative implementations of routines in the spec that +have been optimized for speed rather than clarity. + +They can be monkey patched in during start up by calling the `monkey_patch()` +function. This must be done before those modules are imported anywhere. +*) + +Require importlib. +Require typing. +Require ethereum_spec_tools.forks. +Require ethereum_optimized.fork. +Require ethereum_optimized.state_db. + +Definition monkey_patch_optimized_state_db (fork_name : str) (state_path : (* TODO type *)) : M unit := + (* + Replace the state interface with one that supports high performance + updates and storing state in a database. + + This function must be called before the state interface is imported + anywhere. + *) + do* M.assign "slow_state" [[ + typing.cast ~(| + typing.Any, + importlib.import_module ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "optimized_state_db_patches" [[ + state_db.get_optimized_state_patches ~(| + fork_name + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition monkey_patch_optimized_spec (fork_name : str) : M unit := + (* + Replace the ethash implementation with one that supports higher + performance. + + This function must be called before the spec interface is imported + anywhere. + *) + do* M.assign "slow_spec" [[ + importlib.import_module ~(| + (* TODO expression *) + |) in + ]] in + do* M.assign "optimized_pow_patches" [[ + fork.get_optimized_pow_patches ~(| + fork_name + |) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition monkey_patch (state_path : (* TODO type *)) : M unit := + (* + Apply all monkey patches to the specification. + *) + do* M.assign "forks" [[ + M.get_field ~(| ethereum_spec_tools.forks.Hardfork, "discover" |) ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum_optimized/fork.ast b/coq/ethereum_optimized/fork.ast new file mode 100644 index 0000000000..f0192c16aa --- /dev/null +++ b/coq/ethereum_optimized/fork.ast @@ -0,0 +1,252 @@ +Module( + body=[ + Expr( + value=Constant(value='\nOptimized Spec\n^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis module contains optimized POW functions can be monkey patched into the\n`fork` module of a fork.\n')), + ImportFrom( + module='importlib', + names=[ + alias(name='import_module')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Any'), + alias(name='Dict'), + alias(name='cast')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.ethash', + names=[ + alias(name='epoch')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='InvalidBlock')], + level=0), + ImportFrom( + module='utils', + names=[ + alias(name='add_item')], + level=1), + Try( + body=[ + Import( + names=[ + alias(name='ethash')])], + handlers=[ + ExceptHandler( + type=Name(id='ImportError', ctx=Load()), + name='e', + body=[ + Raise( + exc=Name(id='e', ctx=Load()), + cause=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value="Install with `pip install 'ethereum[optimized]'` to enable this package")], + keywords=[]))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='Header_', ctx=Store())], + value=Name(id='Any', ctx=Load())), + FunctionDef( + name='get_optimized_pow_patches', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='_fork_name', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a dictionary of patches to be patched into the fork to make it\n optimized.\n ')), + AnnAssign( + target=Name(id='patches', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='str', ctx=Load()), + Name(id='Any', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + Assign( + targets=[ + Name(id='mod', ctx=Store())], + value=Call( + func=Name(id='cast', ctx=Load()), + args=[ + Name(id='Any', ctx=Load()), + Call( + func=Name(id='import_module', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value='ethereum.'), + op=Add(), + right=Name(id='_fork_name', ctx=Load())), + op=Add(), + right=Constant(value='.fork'))], + keywords=[])], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='hasattr', ctx=Load()), + args=[ + Name(id='mod', ctx=Load()), + Constant(value='validate_proof_of_work')], + keywords=[])), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value='Attempted to get optimized pow patches for non-pow fork')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='generate_header_hash_for_pow', ctx=Store())], + value=Attribute( + value=Name(id='mod', ctx=Load()), + attr='generate_header_hash_for_pow', + ctx=Load())), + FunctionDef( + name='validate_proof_of_work', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='header', + annotation=Name(id='Header_', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `validate_proof_of_work`.\n ')), + Assign( + targets=[ + Name(id='epoch_number', ctx=Store())], + value=Call( + func=Name(id='epoch', ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='header_hash', ctx=Store())], + value=Call( + func=Name(id='generate_header_hash_for_pow', ctx=Load()), + args=[ + Name(id='header', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='limit', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Attribute( + value=Name(id='U256', ctx=Load()), + attr='MAX_VALUE', + ctx=Load())], + keywords=[]), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='ethash', ctx=Load()), + attr='verify', + ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='epoch_number', ctx=Load())], + keywords=[]), + Name(id='header_hash', ctx=Load()), + Attribute( + value=Name(id='header', ctx=Load()), + attr='mix_digest', + ctx=Load()), + Call( + func=Attribute( + value=Name(id='int', ctx=Load()), + attr='from_bytes', + ctx=Load()), + args=[ + Attribute( + value=Name(id='header', ctx=Load()), + attr='nonce', + ctx=Load()), + Constant(value='big')], + keywords=[]), + Call( + func=Attribute( + value=BinOp( + left=Name(id='limit', ctx=Load()), + op=FloorDiv(), + right=Attribute( + value=Name(id='header', ctx=Load()), + attr='difficulty', + ctx=Load())), + attr='to_be_bytes32', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Name(id='result', ctx=Load())), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None)), + Return( + value=Name(id='patches', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='str', ctx=Load()), + Name(id='Any', ctx=Load())], + ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_optimized/fork.v b/coq/ethereum_optimized/fork.v new file mode 100644 index 0000000000..a963aedb73 --- /dev/null +++ b/coq/ethereum_optimized/fork.v @@ -0,0 +1,44 @@ +(* Generated *) +(* +Optimized Spec +^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This module contains optimized POW functions can be monkey patched into the +`fork` module of a fork. +*) + +Require importlib. +Require typing. +Require ethereum_types.numeric. +Require ethereum.ethash. +Require ethereum.exceptions. +Require ethereum_optimized.utils. + +Definition get_optimized_pow_patches (_fork_name : str) : M (* TODO type *) := + (* + Get a dictionary of patches to be patched into the fork to make it + optimized. + *) + (* TODO statement *) + do* M.assign "mod" [[ + typing.cast ~(| + typing.Any, + importlib.import_module ~(| + (* TODO expression *) + |) + |) in + ]] in + (* TODO statement *) + do* M.assign "generate_header_hash_for_pow" [[ + M.get_field ~(| M.get_local ~(| "mod" |), "generate_header_hash_for_pow" |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum_optimized/state_db.ast b/coq/ethereum_optimized/state_db.ast new file mode 100644 index 0000000000..12bb2c8288 --- /dev/null +++ b/coq/ethereum_optimized/state_db.ast @@ -0,0 +1,2332 @@ +Module( + body=[ + Expr( + value=Constant(value="\nOptimized State\n^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nThis module contains functions can be monkey patched into the fork's `state`\nmodule to use an optimized database backed state.\n")), + Import( + names=[ + alias(name='logging')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='importlib', + names=[ + alias(name='import_module')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Any'), + alias(name='ClassVar'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Set'), + alias(name='cast')], + level=0), + Try( + body=[ + Import( + names=[ + alias(name='rust_pyspec_glue')])], + handlers=[ + ExceptHandler( + type=Name(id='ImportError', ctx=Load()), + name='e', + body=[ + Raise( + exc=Name(id='e', ctx=Load()), + cause=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value="Install with `pip install 'ethereum[optimized]'` to enable this package")], + keywords=[]))])], + orelse=[], + finalbody=[]), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes20')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='utils', + names=[ + alias(name='add_item')], + level=1), + Assign( + targets=[ + Name(id='Address', ctx=Store())], + value=Name(id='Bytes20', ctx=Load())), + Assign( + targets=[ + Name(id='Root', ctx=Store())], + value=Name(id='Hash32', ctx=Load())), + Assign( + targets=[ + Name(id='Account_', ctx=Store())], + value=Name(id='Any', ctx=Load())), + ClassDef( + name='UnmodifiedType', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value="\n Sentinel type to represent a value that hasn't been modified.\n ")), + Pass()], + decorator_list=[]), + Assign( + targets=[ + Name(id='Unmodified', ctx=Store())], + value=Call( + func=Name(id='UnmodifiedType', ctx=Load()), + args=[], + keywords=[])), + FunctionDef( + name='get_optimized_state_patches', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='fork', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a dictionary of functions/objects to be monkey patched into the state\n to make it optimized.\n ')), + AnnAssign( + target=Name(id='patches', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='str', ctx=Load()), + Name(id='Any', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + Assign( + targets=[ + Name(id='types_mod', ctx=Store())], + value=Call( + func=Name(id='cast', ctx=Load()), + args=[ + Name(id='Any', ctx=Load()), + Call( + func=Name(id='import_module', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value='ethereum.'), + op=Add(), + right=Name(id='fork', ctx=Load())), + op=Add(), + right=Constant(value='.fork_types'))], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='state_mod', ctx=Store())], + value=Call( + func=Name(id='cast', ctx=Load()), + args=[ + Name(id='Any', ctx=Load()), + Call( + func=Name(id='import_module', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value='ethereum.'), + op=Add(), + right=Name(id='fork', ctx=Load())), + op=Add(), + right=Constant(value='.state'))], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='Account', ctx=Store())], + value=Attribute( + value=Name(id='types_mod', ctx=Load()), + attr='Account', + ctx=Load())), + Assign( + targets=[ + Name(id='has_transient_storage', ctx=Store())], + value=Call( + func=Name(id='hasattr', ctx=Load()), + args=[ + Name(id='state_mod', ctx=Load()), + Constant(value='TransientStorage')], + keywords=[])), + ClassDef( + name='State', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The State, backed by a LMDB database.\n\n When created with `State()` store the db in a temporary directory. When\n created with `State(path)` open or create the db located at `path`.\n ')), + AnnAssign( + target=Name(id='default_path', ctx=Store()), + annotation=Subscript( + value=Name(id='ClassVar', ctx=Load()), + slice=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Constant(value=None), + simple=1), + AnnAssign( + target=Name(id='db', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='dirty_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account_', ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='dirty_storage', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Address', ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Bytes', ctx=Load()), + Name(id='U256', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='destroyed_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='tx_restore_points', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='journal', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Any', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='created_accounts', ctx=Store()), + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Address', ctx=Load()), + ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='path', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='logging', ctx=Load()), + attr='info', + ctx=Load()), + args=[ + Constant(value='using optimized state db at %s'), + Name(id='path', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='path', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='path', ctx=Store())], + value=Attribute( + value=Name(id='State', ctx=Load()), + attr='default_path', + ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='db', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rust_pyspec_glue', ctx=Load()), + attr='DB', + ctx=Load()), + args=[ + Name(id='path', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='dirty_accounts', + ctx=Store())], + value=Dict(keys=[], values=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='dirty_storage', + ctx=Store())], + value=Dict(keys=[], values=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='destroyed_accounts', + ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='tx_restore_points', + ctx=Store())], + value=List(elts=[], ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='journal', + ctx=Store())], + value=List(elts=[], ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='created_accounts', + ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='db', + ctx=Load()), + attr='begin_mutable', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='__eq__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='other', + annotation=Name(id='object', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Test for equality by comparing state roots.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='other', ctx=Load()), + Name(id='State', ctx=Load())], + keywords=[])), + body=[ + Return( + value=Name(id='NotImplemented', ctx=Load()))], + orelse=[]), + Return( + value=Compare( + left=Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='state_root', ctx=Load()), + args=[ + Name(id='other', ctx=Load())], + keywords=[])]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='__enter__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Support with statements')), + Return( + value=Name(id='self', ctx=Load()))], + decorator_list=[], + returns=Constant(value='State')), + FunctionDef( + name='__exit__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + vararg=arg( + arg='args', + annotation=Name(id='Any', ctx=Load())), + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Support with statements')), + Expr( + value=Call( + func=Name(id='close_state', ctx=Load()), + args=[ + Name(id='self', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[]), + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Close a state, releasing all resources it holds')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Load()), + attr='close', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Store())], + value=Constant(value=None)), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_accounts', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='destroyed_accounts', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='journal', + ctx=Del())]), + Delete( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Del())])], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None)), + FunctionDef( + name='get_metadata', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get a piece of metadata')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Load()), + attr='get_metadata', + ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_metadata', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Set a piece of metadata')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Load()), + attr='set_metadata', + ctx=Load()), + args=[ + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None)), + FunctionDef( + name='begin_db_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Start a database transaction. A transaction is automatically started\n when a `State` is created. Nesting of DB transactions is not supported\n (unlike non-db transactions).\n\n No operations are supported when not in a transaction.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Load()), + attr='begin_mutable', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='tx_restore_points', + ctx=Store())], + value=List(elts=[], ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='journal', + ctx=Store())], + value=List(elts=[], ctx=Load()))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None)), + FunctionDef( + name='commit_db_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Commit the current database transaction.\n ')), + If( + test=Attribute( + value=Name(id='state', ctx=Load()), + attr='tx_restore_points', + ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value='In a non-db transaction')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='flush', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Load()), + attr='commit_mutable', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None)), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + If( + test=Attribute( + value=Name(id='state', ctx=Load()), + attr='tx_restore_points', + ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value='In a non-db transaction')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='flush', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Load()), + attr='state_root', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='storage_root', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + If( + test=Attribute( + value=Name(id='state', ctx=Load()), + attr='tx_restore_points', + ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value='In a non-db transaction')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Name(id='flush', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Load()), + attr='storage_root', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Name(id='Root', ctx=Load())), + FunctionDef( + name='flush', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Send everything in the internal caches to the Rust layer.\n ')), + If( + test=Attribute( + value=Name(id='state', ctx=Load()), + attr='tx_restore_points', + ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value='In a non-db transaction')], + keywords=[]))], + orelse=[]), + For( + target=Name(id='address', ctx=Store()), + iter=Attribute( + value=Name(id='state', ctx=Load()), + attr='destroyed_accounts', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Load()), + attr='destroy_storage', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='address', ctx=Store()), + Name(id='account', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_accounts', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Load()), + attr='set_account', + ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='address', ctx=Store()), + Name(id='storage', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='key', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='storage', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Load()), + attr='set_storage', + ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='value', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='destroyed_accounts', + ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None)), + FunctionDef( + name='rollback_db_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Rollback the current database transaction.\n ')), + If( + test=Attribute( + value=Name(id='state', ctx=Load()), + attr='tx_restore_points', + ctx=Load()), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value='In a non-db transaction')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Load()), + attr='rollback_mutable', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='destroyed_accounts', + ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None)), + FunctionDef( + name='_begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='tx_restore_points', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Name(id='flush', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='tx_restore_points', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='journal', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + If( + test=Name(id='has_transient_storage', ctx=Load()), + body=[ + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='transient_storage', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Any', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n See `state`\n ')), + Expr( + value=Call( + func=Name(id='_begin_transaction', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='transient_storage', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Attribute( + value=Name(id='state_mod', ctx=Load()), + attr='copy_trie', + ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[])], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None))], + orelse=[ + FunctionDef( + name='begin_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`\n ')), + Expr( + value=Call( + func=Name(id='_begin_transaction', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[]))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None))]), + FunctionDef( + name='_commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='tx_restore_points', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='tx_restore_points', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='journal', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Name(id='flush', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + If( + test=Name(id='has_transient_storage', ctx=Load()), + body=[ + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='transient_storage', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Any', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + Expr( + value=Call( + func=Name(id='_commit_transaction', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Name(id='transient_storage', ctx=Load()), + Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_snapshots', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None))], + orelse=[ + FunctionDef( + name='commit_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + Expr( + value=Call( + func=Name(id='_commit_transaction', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[]))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None))]), + FunctionDef( + name='_rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + Assign( + targets=[ + Name(id='restore_point', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='tx_restore_points', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + While( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='journal', + ctx=Load())], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Name(id='restore_point', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='item', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='journal', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='item', ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=3)]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value=2), + ctx=Load()), + ops=[ + Is()], + comparators=[ + Name(id='Unmodified', ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load()), + slice=Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ctx=Load()), + slice=Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value=1), + ctx=Load()), + ctx=Del())])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load()), + slice=Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ctx=Load()), + slice=Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value=1), + ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value=2), + ctx=Load()))])], + orelse=[ + If( + test=Compare( + left=Call( + func=Name(id='type', ctx=Load()), + args=[ + Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[]), + ops=[ + Is()], + comparators=[ + Name(id='dict', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='destroyed_accounts', + ctx=Load()), + attr='remove', + ctx=Load()), + args=[ + Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load()), + slice=Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value=1), + ctx=Load()))], + orelse=[ + If( + test=Compare( + left=Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value=1), + ctx=Load()), + ops=[ + Is()], + comparators=[ + Name(id='Unmodified', ctx=Load())]), + body=[ + Delete( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_accounts', + ctx=Load()), + slice=Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ctx=Del())])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_accounts', + ctx=Load()), + slice=Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value=1), + ctx=Load()))])])])], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='state', ctx=Load()), + attr='tx_restore_points', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + If( + test=Name(id='has_transient_storage', ctx=Load()), + body=[ + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='transient_storage', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Any', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n See `state`\n ')), + Expr( + value=Call( + func=Name(id='_rollback_transaction', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Name(id='transient_storage', ctx=Load()), + Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_snapshots', + ctx=Load())]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_tries', + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='transient_storage', ctx=Load()), + attr='_snapshots', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None))], + orelse=[ + FunctionDef( + name='rollback_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + Expr( + value=Call( + func=Name(id='_rollback_transaction', ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[]))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None))]), + FunctionDef( + name='get_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load())]), + Compare( + left=Name(id='key', ctx=Load()), + ops=[ + In()], + comparators=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())])]), + body=[ + Return( + value=Subscript( + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='destroyed_accounts', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Load()), + attr='get_storage', + ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='get_storage_original', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load())]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Load()), + attr='get_storage', + ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Name(id='key', ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='key', + annotation=Name(id='Bytes', ctx=Load())), + arg( + arg='value', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_accounts', + ctx=Load())]), + body=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_accounts', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load())]), + body=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Dict(keys=[], values=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='journal', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Name(id='address', ctx=Load()), + Name(id='key', ctx=Load()), + Name(id='Unmodified', ctx=Load())], + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='journal', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Name(id='address', ctx=Load()), + Name(id='key', ctx=Load()), + Subscript( + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Load())], + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Subscript( + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None)), + FunctionDef( + name='get_account_optional', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_accounts', + ctx=Load())]), + body=[ + Return( + value=Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_accounts', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='db', + ctx=Load()), + attr='get_account_optional', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='account', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Name(id='Account', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Subscript( + value=Name(id='account', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Subscript( + value=Name(id='account', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[]), + Subscript( + value=Name(id='account', ctx=Load()), + slice=Constant(value=2), + ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Constant(value=None))])], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account_', ctx=Load()), + ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load())), + arg( + arg='account', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Account_', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='journal', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Name(id='address', ctx=Load()), + Name(id='Unmodified', ctx=Load())], + ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_accounts', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='journal', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Name(id='address', ctx=Load()), + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_accounts', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load())], + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_accounts', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Store())], + value=Name(id='account', ctx=Load()))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None)), + FunctionDef( + name='destroy_storage', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='journal', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Name(id='address', ctx=Load()), + Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='dirty_storage', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[ + Name(id='address', ctx=Load()), + Dict(keys=[], values=[])], + keywords=[])], + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='destroyed_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='set_account', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='get_account_optional', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None)), + FunctionDef( + name='mark_account_created', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='state', + annotation=Name(id='State', ctx=Load())), + arg( + arg='address', + annotation=Name(id='Address', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n See `state`.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='created_accounts', + ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='address', ctx=Load())], + keywords=[]))], + decorator_list=[ + Call( + func=Name(id='add_item', ctx=Load()), + args=[ + Name(id='patches', ctx=Load())], + keywords=[])], + returns=Constant(value=None)), + Return( + value=Name(id='patches', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='str', ctx=Load()), + Name(id='Any', ctx=Load())], + ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_optimized/state_db.v b/coq/ethereum_optimized/state_db.v new file mode 100644 index 0000000000..d7c6ba74f1 --- /dev/null +++ b/coq/ethereum_optimized/state_db.v @@ -0,0 +1,73 @@ +(* Generated *) +(* +Optimized State +^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +This module contains functions can be monkey patched into the fork's `state` +module to use an optimized database backed state. +*) + + +Definition get_optimized_state_patches (fork : str) : M (* TODO type *) := + (* + Get a dictionary of functions/objects to be monkey patched into the state + to make it optimized. + *) + (* TODO statement *) + do* M.assign "types_mod" [[ + M.get_local ~(| "cast" |) ~(| + M.get_local ~(| "Any" |), + M.get_local ~(| "import_module" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "state_mod" [[ + M.get_local ~(| "cast" |) ~(| + M.get_local ~(| "Any" |), + M.get_local ~(| "import_module" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "Account" [[ + M.get_field ~(| M.get_local ~(| "types_mod" |), "Account" |) in + ]] in + do* M.assign "has_transient_storage" [[ + M.get_local ~(| "hasattr" |) ~(| + M.get_local ~(| "state_mod" |), + (* TODO constant *) + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum_optimized/utils.ast b/coq/ethereum_optimized/utils.ast new file mode 100644 index 0000000000..7c4707e9a6 --- /dev/null +++ b/coq/ethereum_optimized/utils.ast @@ -0,0 +1,62 @@ +Module( + body=[ + Expr( + value=Constant(value='\nOptimized Implementation Utilities\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n.. contents:: Table of Contents\n :backlinks: none\n :local:\n\nIntroduction\n------------\n\nUtility functions for optimized implementations.\n')), + ImportFrom( + module='typing', + names=[ + alias(name='Any'), + alias(name='Dict')], + level=0), + FunctionDef( + name='add_item', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='patches', + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='str', ctx=Load()), + Name(id='Any', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Decorator to add a function to a patches dictionary.\n ')), + FunctionDef( + name='inner', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='f', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='patches', ctx=Load()), + slice=Attribute( + value=Name(id='f', ctx=Load()), + attr='__name__', + ctx=Load()), + ctx=Store())], + value=Name(id='f', ctx=Load())), + Return( + value=Name(id='f', ctx=Load()))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + Return( + value=Name(id='inner', ctx=Load()))], + decorator_list=[], + returns=Name(id='Any', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_optimized/utils.v b/coq/ethereum_optimized/utils.v new file mode 100644 index 0000000000..572ca2dab3 --- /dev/null +++ b/coq/ethereum_optimized/utils.v @@ -0,0 +1,24 @@ +(* Generated *) +(* +Optimized Implementation Utilities +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Table of Contents + :backlinks: none + :local: + +Introduction +------------ + +Utility functions for optimized implementations. +*) + +Require typing. + +Definition add_item (patches : (* TODO type *)) : M Any := + (* + Decorator to add a function to a patches dictionary. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum_spec_tools/__init__.ast b/coq/ethereum_spec_tools/__init__.ast new file mode 100644 index 0000000000..8c4f02a80b --- /dev/null +++ b/coq/ethereum_spec_tools/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Specification Tools\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\nLibrary of utilities and tools necessary for rendering (or otherwise working\nwith) the Ethereum specifications.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/__init__.v b/coq/ethereum_spec_tools/__init__.v new file mode 100644 index 0000000000..95c161e0b1 --- /dev/null +++ b/coq/ethereum_spec_tools/__init__.v @@ -0,0 +1,9 @@ +(* Generated *) +(* +Ethereum Specification Tools +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Library of utilities and tools necessary for rendering (or otherwise working +with) the Ethereum specifications. +*) + diff --git a/coq/ethereum_spec_tools/docc.ast b/coq/ethereum_spec_tools/docc.ast new file mode 100644 index 0000000000..80ac1bdad4 --- /dev/null +++ b/coq/ethereum_spec_tools/docc.ast @@ -0,0 +1,6555 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPlugins for docc specific to the Ethereum execution specification.\n')), + Import( + names=[ + alias(name='dataclasses')]), + Import( + names=[ + alias(name='logging')]), + ImportFrom( + module='collections', + names=[ + alias(name='defaultdict')], + level=0), + ImportFrom( + module='itertools', + names=[ + alias(name='tee'), + alias(name='zip_longest')], + level=0), + ImportFrom( + module='pathlib', + names=[ + alias(name='PurePath')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Dict'), + alias(name='Final'), + alias(name='FrozenSet'), + alias(name='Generic'), + alias(name='Iterable'), + alias(name='Iterator'), + alias(name='List'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='Set'), + alias(name='Tuple'), + alias(name='Type'), + alias(name='TypeVar'), + alias(name='Union')], + level=0), + ImportFrom( + module='docc.context', + names=[ + alias(name='Context')], + level=0), + ImportFrom( + module='docc.discover', + names=[ + alias(name='Discover'), + alias(name='T')], + level=0), + ImportFrom( + module='docc.document', + names=[ + alias(name='BlankNode'), + alias(name='Document'), + alias(name='ListNode'), + alias(name='Node'), + alias(name='Visit'), + alias(name='Visitor')], + level=0), + ImportFrom( + module='docc.plugins', + names=[ + alias(name='html'), + alias(name='mistletoe'), + alias(name='python'), + alias(name='verbatim')], + level=0), + ImportFrom( + module='docc.plugins.listing', + names=[ + alias(name='Listable')], + level=0), + ImportFrom( + module='docc.plugins.python', + names=[ + alias(name='PythonBuilder')], + level=0), + ImportFrom( + module='docc.plugins.references', + names=[ + alias(name='Definition'), + alias(name='Reference')], + level=0), + ImportFrom( + module='docc.settings', + names=[ + alias(name='PluginSettings')], + level=0), + ImportFrom( + module='docc.source', + names=[ + alias(name='Source')], + level=0), + ImportFrom( + module='docc.transform', + names=[ + alias(name='Transform')], + level=0), + ImportFrom( + module='fladrif.apply', + names=[ + alias(name='Apply')], + level=0), + ImportFrom( + module='fladrif.treediff', + names=[ + alias(name='Adapter'), + alias(name='Operation'), + alias(name='TreeMatcher')], + level=0), + ImportFrom( + module='mistletoe', + names=[ + alias(name='block_token', asname='blocks')], + level=0), + ImportFrom( + module='mistletoe', + names=[ + alias(name='span_token', asname='spans')], + level=0), + ImportFrom( + module='typing_extensions', + names=[ + alias(name='assert_never')], + level=0), + ImportFrom( + module='forks', + names=[ + alias(name='Hardfork')], + level=1), + Assign( + targets=[ + Name(id='G', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='G')], + keywords=[])), + FunctionDef( + name='pairwise', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='iterable', + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='G', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n ABCDEFG --> AB BC CD DE EF FG\n ')), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='a', ctx=Store()), + Name(id='b', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='tee', ctx=Load()), + args=[ + Name(id='iterable', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='next', ctx=Load()), + args=[ + Name(id='b', ctx=Load()), + Constant(value=None)], + keywords=[])), + Return( + value=Call( + func=Name(id='zip', ctx=Load()), + args=[ + Name(id='a', ctx=Load()), + Name(id='b', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='G', ctx=Load()), + Name(id='G', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())), + ClassDef( + name='EthereumDiscover', + bases=[ + Name(id='Discover', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Creates sources that represent the diff between two other sources, one per\n fork.\n ')), + AnnAssign( + target=Name(id='forks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hardfork', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='settings', ctx=Store()), + annotation=Name(id='PluginSettings', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='config', + annotation=Name(id='PluginSettings', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='settings', + ctx=Store())], + value=Name(id='config', ctx=Load())), + Assign( + targets=[ + Name(id='base', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='config', ctx=Load()), + attr='resolve_path', + ctx=Load()), + args=[ + BinOp( + left=Call( + func=Name(id='PurePath', ctx=Load()), + args=[ + Constant(value='src')], + keywords=[]), + op=Div(), + right=Constant(value='ethereum'))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='forks', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Hardfork', ctx=Load()), + attr='discover', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='base', + value=Name(id='base', ctx=Load()))]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='discover', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='known', + annotation=Subscript( + value=Name(id='FrozenSet', ctx=Load()), + slice=Name(id='T', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Find sources.\n ')), + Assign( + targets=[ + Name(id='forks', ctx=Store())], + value=DictComp( + key=Attribute( + value=Name(id='f', ctx=Load()), + attr='path', + ctx=Load()), + value=Name(id='f', ctx=Load()), + generators=[ + comprehension( + target=Name(id='f', ctx=Store()), + iter=Attribute( + value=Name(id='self', ctx=Load()), + attr='forks', + ctx=Load()), + ifs=[ + Compare( + left=Attribute( + value=Name(id='f', ctx=Load()), + attr='path', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])], + is_async=0)])), + AnnAssign( + target=Name(id='by_fork', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Hardfork', ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='PurePath', ctx=Load()), + Name(id='Source', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='defaultdict', ctx=Load()), + args=[ + Name(id='dict', ctx=Load())], + keywords=[]), + simple=1), + For( + target=Name(id='source', ctx=Store()), + iter=Name(id='known', ctx=Load()), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='source', ctx=Load()), + attr='relative_path', + ctx=Load())), + body=[ + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='absolute_path', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='settings', + ctx=Load()), + attr='resolve_path', + ctx=Load()), + args=[ + Attribute( + value=Name(id='source', ctx=Load()), + attr='relative_path', + ctx=Load())], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='fork_path', ctx=Store()), + Name(id='fork_fork', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='forks', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='fork_relative_path', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='absolute_path', ctx=Load()), + attr='relative_to', + ctx=Load()), + args=[ + Name(id='fork_path', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='fork', ctx=Store())], + value=Name(id='fork_fork', ctx=Load())), + Break()], + handlers=[ + ExceptHandler( + type=Name(id='ValueError', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='logging', ctx=Load()), + attr='debug', + ctx=Load()), + args=[ + Constant(value='source `%s` is not part of fork `%s`'), + Attribute( + value=Name(id='source', ctx=Load()), + attr='relative_path', + ctx=Load()), + Attribute( + value=Name(id='fork_fork', ctx=Load()), + attr='short_name', + ctx=Load())], + keywords=[ + keyword( + arg='exc_info', + value=Constant(value=True))]))])], + orelse=[], + finalbody=[])], + orelse=[ + Continue()]), + If( + test=Compare( + left=Name(id='fork_relative_path', ctx=Load()), + ops=[ + In()], + comparators=[ + Subscript( + value=Name(id='by_fork', ctx=Load()), + slice=Name(id='fork', ctx=Load()), + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='two sources claim same path `'), + FormattedValue( + value=Name(id='fork_relative_path', ctx=Load()), + conversion=-1), + Constant(value='`')])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='by_fork', ctx=Load()), + slice=Name(id='fork', ctx=Load()), + ctx=Load()), + slice=Name(id='fork_relative_path', ctx=Load()), + ctx=Store())], + value=Name(id='source', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='diff_count', ctx=Store())], + value=Constant(value=0)), + For( + target=Tuple( + elts=[ + Name(id='before', ctx=Store()), + Name(id='after', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='pairwise', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='forks', + ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='paths', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='set', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Subscript( + value=Name(id='by_fork', ctx=Load()), + slice=Name(id='before', ctx=Load()), + ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + op=BitOr(), + right=Call( + func=Name(id='set', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Subscript( + value=Name(id='by_fork', ctx=Load()), + slice=Name(id='after', ctx=Load()), + ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]))), + For( + target=Name(id='path', ctx=Store()), + iter=Name(id='paths', ctx=Load()), + body=[ + AugAssign( + target=Name(id='diff_count', ctx=Store()), + op=Add(), + value=Constant(value=1)), + Assign( + targets=[ + Name(id='before_source', ctx=Store())], + value=Call( + func=Attribute( + value=Subscript( + value=Name(id='by_fork', ctx=Load()), + slice=Name(id='before', ctx=Load()), + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='path', ctx=Load()), + Constant(value=None)], + keywords=[])), + Assign( + targets=[ + Name(id='after_source', ctx=Store())], + value=Call( + func=Attribute( + value=Subscript( + value=Name(id='by_fork', ctx=Load()), + slice=Name(id='after', ctx=Load()), + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='path', ctx=Load()), + Constant(value=None)], + keywords=[])), + Assert( + test=BoolOp( + op=Or(), + values=[ + Name(id='before_source', ctx=Load()), + Name(id='after_source', ctx=Load())])), + Assign( + targets=[ + Name(id='output_path', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Call( + func=Name(id='PurePath', ctx=Load()), + args=[ + Constant(value='diffs')], + keywords=[]), + op=Div(), + right=Attribute( + value=Name(id='before', ctx=Load()), + attr='short_name', + ctx=Load())), + op=Div(), + right=Attribute( + value=Name(id='after', ctx=Load()), + attr='short_name', + ctx=Load())), + op=Div(), + right=Name(id='path', ctx=Load()))), + Expr( + value=Yield( + value=Call( + func=Name(id='DiffSource', ctx=Load()), + args=[ + Attribute( + value=Name(id='before', ctx=Load()), + attr='name', + ctx=Load()), + Name(id='before_source', ctx=Load()), + Attribute( + value=Name(id='after', ctx=Load()), + attr='name', + ctx=Load()), + Name(id='after_source', ctx=Load()), + Name(id='output_path', ctx=Load())], + keywords=[])))], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Constant(value=0), + ops=[ + Eq()], + comparators=[ + Name(id='diff_count', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value='no diff pairs found')], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='logging', ctx=Load()), + attr='info', + ctx=Load()), + args=[ + Constant(value='Discovered %s pair(s) of sources to diff'), + Name(id='diff_count', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Iterator', ctx=Load()), + slice=Name(id='Source', ctx=Load()), + ctx=Load()))], + decorator_list=[]), + Assign( + targets=[ + Name(id='S', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='S')], + keywords=[ + keyword( + arg='bound', + value=Name(id='Source', ctx=Load()))])), + ClassDef( + name='DiffSource', + bases=[ + Subscript( + value=Name(id='Generic', ctx=Load()), + slice=Name(id='S', ctx=Load()), + ctx=Load()), + Name(id='Source', ctx=Load()), + Name(id='Listable', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A source that represents the difference between two other sources.\n ')), + AnnAssign( + target=Name(id='before_name', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='before', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='S', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='after_name', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='after', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='S', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_output_path', ctx=Store()), + annotation=Name(id='PurePath', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='before_name', + annotation=Name(id='str', ctx=Load())), + arg( + arg='before', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='S', ctx=Load()), + ctx=Load())), + arg( + arg='after_name', + annotation=Name(id='str', ctx=Load())), + arg( + arg='after', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='S', ctx=Load()), + ctx=Load())), + arg( + arg='output_path', + annotation=Name(id='PurePath', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='before_name', + ctx=Store())], + value=Name(id='before_name', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='before', + ctx=Store())], + value=Name(id='before', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='after_name', + ctx=Store())], + value=Name(id='after_name', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='after', + ctx=Store())], + value=Name(id='after', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_output_path', + ctx=Store())], + value=Name(id='output_path', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='show_in_listing', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n True if this source should appear in directory listings.\n ')), + Return( + value=Constant(value=True))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='relative_path', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Path to the Source (if one exists) relative to the project root.\n ')), + Return( + value=Constant(value=None))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='PurePath', ctx=Load()), + ctx=Load())), + FunctionDef( + name='output_path', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Where to write the output from this Source relative to the output path.\n ')), + Return( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_output_path', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='PurePath', ctx=Load()))], + decorator_list=[]), + ClassDef( + name='AfterNode', + bases=[ + Name(id='Node', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Represents content that was added in a diff.\n ')), + AnnAssign( + target=Name(id='child', ctx=Store()), + annotation=Name(id='Node', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='child', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='child', + ctx=Store())], + value=Name(id='child', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='children', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Child nodes belonging to this node.\n ')), + Return( + value=Tuple( + elts=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='child', + ctx=Load())], + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load())), + FunctionDef( + name='replace_child', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='old', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='new', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Replace the old node with the given new node.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='child', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='old', ctx=Load())]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='child', + ctx=Store())], + value=Name(id='new', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='__repr__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n String representation of this node.\n ')), + Return( + value=Constant(value=''))], + decorator_list=[], + returns=Name(id='str', ctx=Load()))], + decorator_list=[]), + ClassDef( + name='BeforeNode', + bases=[ + Name(id='Node', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Represents content that was removed in a diff.\n ')), + AnnAssign( + target=Name(id='child', ctx=Store()), + annotation=Name(id='Node', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='child', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='child', + ctx=Store())], + value=Name(id='child', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='children', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Child nodes belonging to this node.\n ')), + Return( + value=Tuple( + elts=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='child', + ctx=Load())], + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load())), + FunctionDef( + name='replace_child', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='old', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='new', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Replace the old node with the given new node.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='child', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='old', ctx=Load())]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='child', + ctx=Store())], + value=Name(id='new', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='__repr__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n String representation of this node.\n ')), + Return( + value=Constant(value=''))], + decorator_list=[], + returns=Name(id='str', ctx=Load()))], + decorator_list=[]), + ClassDef( + name='DiffNode', + bases=[ + Name(id='Node', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Marks a difference (or patch) with a deletion and an insertion.\n ')), + AnnAssign( + target=Name(id='before_name', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='before', ctx=Store()), + annotation=Name(id='Node', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='after_name', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='after', ctx=Store()), + annotation=Name(id='Node', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='before_name', + annotation=Name(id='str', ctx=Load())), + arg( + arg='before', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='after_name', + annotation=Name(id='str', ctx=Load())), + arg( + arg='after', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='before_name', + ctx=Store())], + value=Name(id='before_name', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='before', + ctx=Store())], + value=Name(id='before', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='after_name', + ctx=Store())], + value=Name(id='after_name', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='after', + ctx=Store())], + value=Name(id='after', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='children', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Child nodes belonging to this node.\n ')), + Return( + value=Tuple( + elts=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='before', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='after', + ctx=Load())], + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Node', ctx=Load()), + Name(id='Node', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='replace_child', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='old', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='new', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Replace the old node with the given new node.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='before', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='old', ctx=Load())]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='before', + ctx=Store())], + value=Name(id='new', ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='after', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='old', ctx=Load())]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='after', + ctx=Store())], + value=Name(id='new', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='__repr__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n String representation of this object.\n ')), + Return( + value=JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='__class__', + ctx=Load()), + attr='__name__', + ctx=Load()), + conversion=-1), + Constant(value='(..., before_name='), + FormattedValue( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='before_name', + ctx=Load()), + conversion=114), + Constant(value=', after_name='), + FormattedValue( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='after_name', + ctx=Load()), + conversion=114), + Constant(value=')')]))], + decorator_list=[], + returns=Name(id='str', ctx=Load()))], + decorator_list=[]), + ClassDef( + name='EthereumBuilder', + bases=[ + Name(id='PythonBuilder', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A `PythonBuilder` that additionally builds `Document`s from `DiffSource`s.\n ')), + FunctionDef( + name='build', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='unprocessed', + annotation=Subscript( + value=Name(id='Set', ctx=Load()), + slice=Name(id='Source', ctx=Load()), + ctx=Load())), + arg( + arg='processed', + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Source', ctx=Load()), + Name(id='Document', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Consume unprocessed Sources and insert their Documents into processed.\n ')), + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='build', + ctx=Load()), + args=[ + Name(id='unprocessed', ctx=Load()), + Name(id='processed', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='source_set', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[ + GeneratorExp( + elt=Name(id='s', ctx=Load()), + generators=[ + comprehension( + target=Name(id='s', ctx=Store()), + iter=Name(id='unprocessed', ctx=Load()), + ifs=[ + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='s', ctx=Load()), + Name(id='DiffSource', ctx=Load())], + keywords=[])], + is_async=0)])], + keywords=[])), + AugAssign( + target=Name(id='unprocessed', ctx=Store()), + op=Sub(), + value=Name(id='source_set', ctx=Load())), + Assign( + targets=[ + Name(id='before_unprocessed', ctx=Store())], + value=SetComp( + elt=Attribute( + value=Name(id='s', ctx=Load()), + attr='before', + ctx=Load()), + generators=[ + comprehension( + target=Name(id='s', ctx=Store()), + iter=Name(id='source_set', ctx=Load()), + ifs=[ + Attribute( + value=Name(id='s', ctx=Load()), + attr='before', + ctx=Load())], + is_async=0)])), + Assign( + targets=[ + Name(id='after_unprocessed', ctx=Store())], + value=SetComp( + elt=Attribute( + value=Name(id='s', ctx=Load()), + attr='after', + ctx=Load()), + generators=[ + comprehension( + target=Name(id='s', ctx=Store()), + iter=Name(id='source_set', ctx=Load()), + ifs=[ + Attribute( + value=Name(id='s', ctx=Load()), + attr='after', + ctx=Load())], + is_async=0)])), + AnnAssign( + target=Name(id='before_processed', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Source', ctx=Load()), + Name(id='Document', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='dict', ctx=Load()), + args=[], + keywords=[]), + simple=1), + AnnAssign( + target=Name(id='after_processed', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Source', ctx=Load()), + Name(id='Document', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Call( + func=Name(id='dict', ctx=Load()), + args=[], + keywords=[]), + simple=1), + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='build', + ctx=Load()), + args=[ + Name(id='before_unprocessed', ctx=Load()), + Name(id='before_processed', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='build', + ctx=Load()), + args=[ + Name(id='after_unprocessed', ctx=Load()), + Name(id='after_processed', ctx=Load())], + keywords=[])), + For( + target=Name(id='diff_source', ctx=Store()), + iter=Name(id='source_set', ctx=Load()), + body=[ + AnnAssign( + target=Name(id='before', ctx=Store()), + annotation=Name(id='Node', ctx=Load()), + value=Call( + func=Name(id='BlankNode', ctx=Load()), + args=[], + keywords=[]), + simple=1), + If( + test=Attribute( + value=Name(id='diff_source', ctx=Load()), + attr='before', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='before_document', ctx=Store())], + value=Subscript( + value=Name(id='before_processed', ctx=Load()), + slice=Attribute( + value=Name(id='diff_source', ctx=Load()), + attr='before', + ctx=Load()), + ctx=Load())), + Delete( + targets=[ + Subscript( + value=Name(id='before_processed', ctx=Load()), + slice=Attribute( + value=Name(id='diff_source', ctx=Load()), + attr='before', + ctx=Load()), + ctx=Del())]), + Assign( + targets=[ + Name(id='before', ctx=Store())], + value=Call( + func=Name(id='BeforeNode', ctx=Load()), + args=[ + Attribute( + value=Name(id='before_document', ctx=Load()), + attr='root', + ctx=Load())], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='after', ctx=Store()), + annotation=Name(id='Node', ctx=Load()), + value=Call( + func=Name(id='BlankNode', ctx=Load()), + args=[], + keywords=[]), + simple=1), + If( + test=Attribute( + value=Name(id='diff_source', ctx=Load()), + attr='after', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='after_document', ctx=Store())], + value=Subscript( + value=Name(id='after_processed', ctx=Load()), + slice=Attribute( + value=Name(id='diff_source', ctx=Load()), + attr='after', + ctx=Load()), + ctx=Load())), + Delete( + targets=[ + Subscript( + value=Name(id='after_processed', ctx=Load()), + slice=Attribute( + value=Name(id='diff_source', ctx=Load()), + attr='after', + ctx=Load()), + ctx=Del())]), + Assign( + targets=[ + Name(id='after', ctx=Store())], + value=Call( + func=Name(id='AfterNode', ctx=Load()), + args=[ + Attribute( + value=Name(id='after_document', ctx=Load()), + attr='root', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='root', ctx=Store())], + value=Call( + func=Name(id='DiffNode', ctx=Load()), + args=[ + Attribute( + value=Name(id='diff_source', ctx=Load()), + attr='before_name', + ctx=Load()), + Name(id='before', ctx=Load()), + Attribute( + value=Name(id='diff_source', ctx=Load()), + attr='after_name', + ctx=Load()), + Name(id='after', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='document', ctx=Store())], + value=Call( + func=Name(id='Document', ctx=Load()), + args=[ + Name(id='root', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Subscript( + value=Name(id='processed', ctx=Load()), + slice=Name(id='diff_source', ctx=Load()), + ctx=Store())], + value=Name(id='document', ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='FixIndexTransform', + bases=[ + Name(id='Transform', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Replaces `Definition` and `Reference` identifiers within `DiffNode` with\n identifiers specific to the diff.\n\n Without fixing these identifiers, every Python class would be defined\n multiples times (the actual definition and then again in each diff),\n cluttering up tables of contents.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='settings', + annotation=Name(id='PluginSettings', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='transform', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='context', + annotation=Name(id='Context', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Apply the transformation to the given document.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Subscript( + value=Name(id='context', ctx=Load()), + slice=Name(id='Document', ctx=Load()), + ctx=Load()), + attr='root', + ctx=Load()), + attr='visit', + ctx=Load()), + args=[ + Call( + func=Name(id='_FixIndexVisitor', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='_FixIndexVisitor', + bases=[ + Name(id='Visitor', ctx=Load())], + keywords=[], + body=[ + AnnAssign( + target=Name(id='diffs', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='DiffNode', ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='diffs', + ctx=Store())], + value=List(elts=[], ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='enter', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='node', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='DiffNode', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='diffs', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[])), + Return( + value=Attribute( + value=Name(id='Visit', ctx=Load()), + attr='TraverseChildren', + ctx=Load()))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='self', ctx=Load()), + attr='diffs', + ctx=Load())), + body=[ + Return( + value=Attribute( + value=Name(id='Visit', ctx=Load()), + attr='TraverseChildren', + ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='diff', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='diffs', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())), + Assign( + targets=[ + Name(id='before', ctx=Store())], + value=Attribute( + value=Name(id='diff', ctx=Load()), + attr='before_name', + ctx=Load())), + Assign( + targets=[ + Name(id='after', ctx=Store())], + value=Attribute( + value=Name(id='diff', ctx=Load()), + attr='after_name', + ctx=Load())), + Assign( + targets=[ + Name(id='before_prefix', ctx=Store())], + value=JoinedStr( + values=[ + FormattedValue( + value=Name(id='before', ctx=Load()), + conversion=-1), + Constant(value='.')])), + Assign( + targets=[ + Name(id='after_prefix', ctx=Store())], + value=JoinedStr( + values=[ + FormattedValue( + value=Name(id='after', ctx=Load()), + conversion=-1), + Constant(value='.')])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Tuple( + elts=[ + Name(id='Reference', ctx=Load()), + Name(id='Definition', ctx=Load())], + ctx=Load())], + keywords=[]), + body=[ + AnnAssign( + target=Name(id='identifier', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + value=Constant(value=None), + simple=1), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='node', ctx=Load()), + attr='identifier', + ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Name(id='before_prefix', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='identifier', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='node', ctx=Load()), + attr='identifier', + ctx=Load()), + attr='removeprefix', + ctx=Load()), + args=[ + Name(id='before_prefix', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='node', ctx=Load()), + attr='identifier', + ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Name(id='after_prefix', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='identifier', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='node', ctx=Load()), + attr='identifier', + ctx=Load()), + attr='removeprefix', + ctx=Load()), + args=[ + Name(id='after_prefix', ctx=Load())], + keywords=[]))], + orelse=[])]), + If( + test=Compare( + left=Name(id='identifier', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='identifier', + ctx=Store())], + value=JoinedStr( + values=[ + Constant(value='diff('), + FormattedValue( + value=Name(id='before', ctx=Load()), + conversion=-1), + Constant(value=','), + FormattedValue( + value=Name(id='after', ctx=Load()), + conversion=-1), + Constant(value=').'), + FormattedValue( + value=Name(id='identifier', ctx=Load()), + conversion=-1)]))], + orelse=[])], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Attribute( + value=Name(id='python', ctx=Load()), + attr='Name', + ctx=Load())], + keywords=[]), + Attribute( + value=Name(id='node', ctx=Load()), + attr='full_name', + ctx=Load())]), + body=[ + If( + test=Attribute( + value=Name(id='node', ctx=Load()), + attr='full_name', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='full_name', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + value=Constant(value=None), + simple=1), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='node', ctx=Load()), + attr='full_name', + ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Name(id='before_prefix', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='full_name', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='node', ctx=Load()), + attr='full_name', + ctx=Load()), + attr='removeprefix', + ctx=Load()), + args=[ + Name(id='before_prefix', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='node', ctx=Load()), + attr='full_name', + ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Name(id='after_prefix', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='full_name', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='node', ctx=Load()), + attr='full_name', + ctx=Load()), + attr='removeprefix', + ctx=Load()), + args=[ + Name(id='after_prefix', ctx=Load())], + keywords=[]))], + orelse=[])]), + If( + test=Compare( + left=Name(id='full_name', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='full_name', + ctx=Store())], + value=JoinedStr( + values=[ + Constant(value='diff('), + FormattedValue( + value=Name(id='before', ctx=Load()), + conversion=-1), + Constant(value=','), + FormattedValue( + value=Name(id='after', ctx=Load()), + conversion=-1), + Constant(value=').'), + FormattedValue( + value=Name(id='full_name', ctx=Load()), + conversion=-1)]))], + orelse=[])], + orelse=[])], + orelse=[])]), + Return( + value=Attribute( + value=Name(id='Visit', ctx=Load()), + attr='TraverseChildren', + ctx=Load()))], + decorator_list=[], + returns=Name(id='Visit', ctx=Load())), + FunctionDef( + name='exit', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='node', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='DiffNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='popped', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='diffs', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + Assert( + test=Compare( + left=Name(id='popped', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='node', ctx=Load())]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='_DoccAdapter', + bases=[ + Subscript( + value=Name(id='Adapter', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + FunctionDef( + name='children', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='node', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=Call( + func=Name(id='list', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='children', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load())), + FunctionDef( + name='_markdown_equals', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='lhs_node', + annotation=Attribute( + value=Name(id='mistletoe', ctx=Load()), + attr='MarkdownNode', + ctx=Load())), + arg( + arg='rhs_node', + annotation=Attribute( + value=Name(id='mistletoe', ctx=Load()), + attr='MarkdownNode', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='lhs', ctx=Store())], + value=Attribute( + value=Name(id='lhs_node', ctx=Load()), + attr='token', + ctx=Load())), + Assign( + targets=[ + Name(id='rhs', ctx=Store())], + value=Attribute( + value=Name(id='rhs_node', ctx=Load()), + attr='token', + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load()), + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load())], + keywords=[])], + keywords=[])), + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load())], + keywords=[])], + keywords=[]))]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Match( + subject=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load())], + keywords=[]), + cases=[ + match_case( + pattern=MatchOr( + patterns=[ + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='Strong', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='Emphasis', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='InlineCode', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='Strikethrough', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='EscapeSequence', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='Quote', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='Paragraph', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='ThematicBreak', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='HTMLBlock', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='AutoLink', + ctx=Load()))]), + body=[ + Return( + value=Constant(value=True))]), + match_case( + pattern=MatchOr( + patterns=[ + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='RawText', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='HTMLSpan', + ctx=Load()))]), + body=[ + Return( + value=Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='content', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='content', + ctx=Load())]))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='Image', + ctx=Load())), + body=[ + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='src', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='src', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='title', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='title', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='label', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='label', + ctx=Load())])]))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='Link', + ctx=Load())), + body=[ + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='target', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='target', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='title', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='title', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='label', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='label', + ctx=Load())])]))]), + match_case( + pattern=MatchOr( + patterns=[ + MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='Heading', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='SetextHeading', + ctx=Load()))]), + body=[ + Return( + value=Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='level', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='level', + ctx=Load())]))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='CodeFence', + ctx=Load())), + body=[ + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='language', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='language', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='info_string', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='info_string', + ctx=Load())])]))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='BlockCode', + ctx=Load())), + body=[ + Return( + value=Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='language', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='language', + ctx=Load())]))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='List', + ctx=Load())), + body=[ + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='loose', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='loose', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='start', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='start', + ctx=Load())])]))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='ListItem', + ctx=Load())), + body=[ + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='loose', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='loose', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='leader', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='leader', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='prepend', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='prepend', + ctx=Load())])]))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='Table', + ctx=Load())), + body=[ + Return( + value=Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='column_align', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='column_align', + ctx=Load())]))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='TableRow', + ctx=Load())), + body=[ + Return( + value=Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='row_align', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='row_align', + ctx=Load())]))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='TableCell', + ctx=Load())), + body=[ + Return( + value=Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='align', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='align', + ctx=Load())]))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='LineBreak', + ctx=Load())), + body=[ + Return( + value=Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='soft', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='soft', + ctx=Load())]))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='Document', + ctx=Load())), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Attribute( + value=Name(id='lhs', ctx=Load()), + attr='footnotes', + ctx=Load()), + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='footnotes', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='logging', ctx=Load()), + attr='warning', + ctx=Load()), + args=[ + Constant(value='markdown footnotes not implemented')], + keywords=[]))], + orelse=[]), + Return( + value=Constant(value=True))]), + match_case( + pattern=MatchAs(), + body=[ + Raise( + exc=Call( + func=Name(id='NotImplementedError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='markdown comparison for '), + FormattedValue( + value=Name(id='lhs', ctx=Load()), + conversion=-1), + Constant(value=' not implemented')])], + keywords=[]))])])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='_markdown_hash', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='node', + annotation=Attribute( + value=Name(id='mistletoe', ctx=Load()), + attr='MarkdownNode', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='token', ctx=Store())], + value=Attribute( + value=Name(id='node', ctx=Load()), + attr='token', + ctx=Load())), + AnnAssign( + target=Name(id='result', ctx=Store()), + annotation=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='object', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + simple=1), + Match( + subject=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='token', ctx=Load())], + keywords=[]), + cases=[ + match_case( + pattern=MatchOr( + patterns=[ + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='Strong', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='Emphasis', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='InlineCode', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='Strikethrough', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='EscapeSequence', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='Quote', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='Paragraph', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='ThematicBreak', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='HTMLBlock', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='AutoLink', + ctx=Load()))]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Tuple(elts=[], ctx=Load()))]), + match_case( + pattern=MatchOr( + patterns=[ + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='RawText', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='HTMLSpan', + ctx=Load()))]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='token', ctx=Load()), + attr='content', + ctx=Load())], + ctx=Load()))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='Link', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='token', ctx=Load()), + attr='target', + ctx=Load()), + Attribute( + value=Name(id='token', ctx=Load()), + attr='title', + ctx=Load()), + Attribute( + value=Name(id='token', ctx=Load()), + attr='label', + ctx=Load())], + ctx=Load()))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='Image', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='token', ctx=Load()), + attr='src', + ctx=Load()), + Attribute( + value=Name(id='token', ctx=Load()), + attr='title', + ctx=Load()), + Attribute( + value=Name(id='token', ctx=Load()), + attr='label', + ctx=Load())], + ctx=Load()))]), + match_case( + pattern=MatchOr( + patterns=[ + MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='Heading', + ctx=Load())), + MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='SetextHeading', + ctx=Load()))]), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='token', ctx=Load()), + attr='level', + ctx=Load())], + ctx=Load()))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='CodeFence', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='token', ctx=Load()), + attr='language', + ctx=Load()), + Attribute( + value=Name(id='token', ctx=Load()), + attr='info_string', + ctx=Load())], + ctx=Load()))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='BlockCode', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='token', ctx=Load()), + attr='language', + ctx=Load())], + ctx=Load()))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='List', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='token', ctx=Load()), + attr='loose', + ctx=Load()), + Attribute( + value=Name(id='token', ctx=Load()), + attr='start', + ctx=Load())], + ctx=Load()))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='ListItem', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='token', ctx=Load()), + attr='loose', + ctx=Load()), + Attribute( + value=Name(id='token', ctx=Load()), + attr='leader', + ctx=Load()), + Attribute( + value=Name(id='token', ctx=Load()), + attr='prepend', + ctx=Load())], + ctx=Load()))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='Table', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='token', ctx=Load()), + attr='column_align', + ctx=Load())], + ctx=Load()))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='TableRow', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='token', ctx=Load()), + attr='row_align', + ctx=Load())], + ctx=Load()))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='TableCell', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='token', ctx=Load()), + attr='align', + ctx=Load())], + ctx=Load()))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='spans', ctx=Load()), + attr='LineBreak', + ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Tuple( + elts=[ + Attribute( + value=Name(id='token', ctx=Load()), + attr='soft', + ctx=Load())], + ctx=Load()))]), + match_case( + pattern=MatchValue( + value=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='Document', + ctx=Load())), + body=[ + If( + test=Attribute( + value=Name(id='token', ctx=Load()), + attr='footnotes', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='logging', ctx=Load()), + attr='warning', + ctx=Load()), + args=[ + Constant(value='markdown footnotes not implemented')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Tuple(elts=[], ctx=Load()))]), + match_case( + pattern=MatchAs(), + body=[ + Raise( + exc=Call( + func=Name(id='NotImplementedError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='markdown hash for '), + FormattedValue( + value=Name(id='token', ctx=Load()), + conversion=-1), + Constant(value=' not implemented')])], + keywords=[]))])]), + Return( + value=Call( + func=Name(id='hash', ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='token', ctx=Load())], + keywords=[]), + Name(id='result', ctx=Load())], + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='shallow_equals', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='lhs', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='rhs', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Name(id='lhs', ctx=Load()), + ops=[ + Is()], + comparators=[ + Name(id='rhs', ctx=Load())]), + body=[ + Return( + value=Constant(value=True))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load())], + keywords=[])], + keywords=[])), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load()), + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load())], + keywords=[])], + keywords=[])), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Attribute( + value=Name(id='python', ctx=Load()), + attr='PythonNode', + ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load()), + Attribute( + value=Name(id='python', ctx=Load()), + attr='PythonNode', + ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_python_equals', + ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Name(id='rhs', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Name(id='Definition', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load()), + Name(id='Definition', ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='identifier', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='identifier', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='specifier', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='specifier', + ctx=Load())])]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Name(id='Reference', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load()), + Name(id='Reference', ctx=Load())], + keywords=[])), + Return( + value=Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='identifier', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='identifier', + ctx=Load())]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Name(id='BlankNode', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load()), + Name(id='BlankNode', ctx=Load())], + keywords=[])), + Return( + value=Constant(value=True))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Attribute( + value=Name(id='mistletoe', ctx=Load()), + attr='MarkdownNode', + ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load()), + Attribute( + value=Name(id='mistletoe', ctx=Load()), + attr='MarkdownNode', + ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_markdown_equals', + ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Name(id='rhs', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Attribute( + value=Name(id='python', ctx=Load()), + attr='Name', + ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load()), + Attribute( + value=Name(id='python', ctx=Load()), + attr='Name', + ctx=Load())], + keywords=[])), + Return( + value=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='name', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='name', + ctx=Load())]), + Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='full_name', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='full_name', + ctx=Load())])]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Name(id='ListNode', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load()), + Name(id='ListNode', ctx=Load())], + keywords=[])), + Return( + value=Constant(value=True))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Transcribed', + ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Transcribed', + ctx=Load())], + keywords=[])), + Return( + value=Constant(value=True))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Line', + ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Line', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='lefts', ctx=Store())], + value=Call( + func=Name(id='list', ctx=Load()), + args=[ + Attribute( + value=Name(id='lhs', ctx=Load()), + attr='children', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='rights', ctx=Store())], + value=Call( + func=Name(id='list', ctx=Load()), + args=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='children', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='lefts', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='rights', ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + Return( + value=Call( + func=Name(id='all', ctx=Load()), + args=[ + GeneratorExp( + elt=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='deep_equals', + ctx=Load()), + args=[ + Name(id='a', ctx=Load()), + Name(id='b', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='a', ctx=Store()), + Name(id='b', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='zip', ctx=Load()), + args=[ + Name(id='lefts', ctx=Load()), + Name(id='rights', ctx=Load())], + keywords=[]), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Highlight', + ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Highlight', + ctx=Load())], + keywords=[])), + Return( + value=Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='highlights', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='highlights', + ctx=Load())]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Text', + ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Text', + ctx=Load())], + keywords=[])), + Return( + value=Compare( + left=Attribute( + value=Name(id='lhs', ctx=Load()), + attr='text', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='rhs', ctx=Load()), + attr='text', + ctx=Load())]))], + orelse=[])])])])])])])])])])]), + Raise( + exc=Call( + func=Name(id='NotImplementedError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='shallow_equals('), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value=', '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value=')')])], + keywords=[]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='_python_hash', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='node', + annotation=Attribute( + value=Name(id='python', ctx=Load()), + attr='PythonNode', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assert( + test=Call( + func=Attribute( + value=Name(id='dataclasses', ctx=Load()), + attr='is_dataclass', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='hash_value', ctx=Store())], + value=Constant(value=0)), + For( + target=Tuple( + elts=[ + Name(id='idx', ctx=Store()), + Name(id='field', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='dataclasses', ctx=Load()), + attr='fields', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='getattr', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Attribute( + value=Name(id='field', ctx=Load()), + attr='name', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='field', ctx=Load()), + attr='type', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='Node', ctx=Load())]), + body=[ + Continue()], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Name(id='field', ctx=Load()), + attr='type', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='ValueError', ctx=Load()), + args=[ + Constant(value="python node fields can't be sequences")], + keywords=[]))], + orelse=[])]), + AugAssign( + target=Name(id='hash_value', ctx=Store()), + op=BitXor(), + value=Call( + func=Name(id='hash', ctx=Load()), + args=[ + Tuple( + elts=[ + Name(id='idx', ctx=Load()), + Name(id='value', ctx=Load())], + ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='hash_value', ctx=Load()))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='_python_equals', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='lhs', + annotation=Attribute( + value=Name(id='python', ctx=Load()), + attr='PythonNode', + ctx=Load())), + arg( + arg='rhs', + annotation=Attribute( + value=Name(id='python', ctx=Load()), + attr='PythonNode', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assert( + test=Call( + func=Attribute( + value=Name(id='dataclasses', ctx=Load()), + attr='is_dataclass', + ctx=Load()), + args=[ + Name(id='lhs', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Attribute( + value=Name(id='dataclasses', ctx=Load()), + attr='is_dataclass', + ctx=Load()), + args=[ + Name(id='rhs', ctx=Load())], + keywords=[])), + Assert( + test=Compare( + left=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load())], + keywords=[]), + ops=[ + Is()], + comparators=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load())], + keywords=[])])), + For( + target=Name(id='field', ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='dataclasses', ctx=Load()), + attr='fields', + ctx=Load()), + args=[ + Name(id='lhs', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='lhs_value', ctx=Store())], + value=Call( + func=Name(id='getattr', ctx=Load()), + args=[ + Name(id='lhs', ctx=Load()), + Attribute( + value=Name(id='field', ctx=Load()), + attr='name', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='rhs_value', ctx=Store())], + value=Call( + func=Name(id='getattr', ctx=Load()), + args=[ + Name(id='rhs', ctx=Load()), + Attribute( + value=Name(id='field', ctx=Load()), + attr='name', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='field', ctx=Load()), + attr='type', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='Node', ctx=Load())]), + body=[ + Continue()], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Name(id='field', ctx=Load()), + attr='type', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='ValueError', ctx=Load()), + args=[ + Constant(value="python node fields can't be sequences")], + keywords=[]))], + orelse=[])]), + If( + test=Compare( + left=Name(id='lhs_value', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='rhs_value', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[])], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='shallow_hash', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='node', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Attribute( + value=Name(id='python', ctx=Load()), + attr='PythonNode', + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_python_hash', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Definition', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='hash', ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='identifier', + ctx=Load()), + Constant(value=None), + Attribute( + value=Name(id='node', ctx=Load()), + attr='specifier', + ctx=Load())], + ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='Reference', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='hash', ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='identifier', + ctx=Load()), + Constant(value=None)], + ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BlankNode', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='hash', ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='BlankNode', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Attribute( + value=Name(id='mistletoe', ctx=Load()), + attr='MarkdownNode', + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_markdown_hash', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Attribute( + value=Name(id='python', ctx=Load()), + attr='Name', + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='hash', ctx=Load()), + args=[ + Tuple( + elts=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='name', + ctx=Load()), + Attribute( + value=Name(id='node', ctx=Load()), + attr='full_name', + ctx=Load())], + ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='ListNode', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='hash', ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='ListNode', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Transcribed', + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='hash', ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Transcribed', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Line', + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='hash', ctx=Load()), + args=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Line', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Highlight', + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='hash', ctx=Load()), + args=[ + Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='highlights', + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Text', + ctx=Load())], + keywords=[]), + body=[ + Return( + value=Call( + func=Name(id='hash', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='text', + ctx=Load())], + keywords=[]))], + orelse=[])])])])])])])])])])]), + Raise( + exc=Call( + func=Name(id='NotImplementedError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='shallow_hash('), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value=')')])], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load()))], + decorator_list=[]), + ClassDef( + name='_HardenVisitor', + bases=[ + Name(id='Visitor', ctx=Load())], + keywords=[], + body=[ + AnnAssign( + target=Name(id='_stack', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_stack', + ctx=Store())], + value=List(elts=[], ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='enter', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='node', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Attribute( + value=Name(id='_DoccApply', ctx=Load()), + attr='FlexNode', + ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_stack', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[])), + Return( + value=Attribute( + value=Name(id='Visit', ctx=Load()), + attr='TraverseChildren', + ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='flex', ctx=Store())], + value=Name(id='node', ctx=Load())), + Assign( + targets=[ + Name(id='wrapped', ctx=Store())], + value=Attribute( + value=Name(id='flex', ctx=Load()), + attr='node', + ctx=Load())), + AnnAssign( + target=Name(id='new_node', ctx=Store()), + annotation=Name(id='Node', ctx=Load()), + simple=1), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='wrapped', ctx=Load()), + Attribute( + value=Name(id='python', ctx=Load()), + attr='PythonNode', + ctx=Load())], + keywords=[]), + body=[ + AnnAssign( + target=Name(id='wrapped_py', ctx=Store()), + annotation=Attribute( + value=Name(id='python', ctx=Load()), + attr='PythonNode', + ctx=Load()), + value=Name(id='wrapped', ctx=Load()), + simple=1), + Assert( + test=Call( + func=Attribute( + value=Name(id='dataclasses', ctx=Load()), + attr='is_dataclass', + ctx=Load()), + args=[ + Name(id='wrapped_py', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='arguments', ctx=Store())], + value=Dict(keys=[], values=[])), + Assign( + targets=[ + Name(id='offset', ctx=Store())], + value=Constant(value=0)), + For( + target=Name(id='field', ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='dataclasses', ctx=Load()), + attr='fields', + ctx=Load()), + args=[ + Name(id='wrapped_py', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='field', ctx=Load()), + attr='type', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='Node', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='flex', ctx=Load()), + attr='children', + ctx=Load()), + slice=Name(id='offset', ctx=Load()), + ctx=Load())), + AugAssign( + target=Name(id='offset', ctx=Store()), + op=Add(), + value=Constant(value=1))], + orelse=[ + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Name(id='getattr', ctx=Load()), + args=[ + Name(id='wrapped', ctx=Load()), + Attribute( + value=Name(id='field', ctx=Load()), + attr='name', + ctx=Load())], + keywords=[]))]), + Assign( + targets=[ + Subscript( + value=Name(id='arguments', ctx=Load()), + slice=Attribute( + value=Name(id='field', ctx=Load()), + attr='name', + ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))], + orelse=[]), + Assert( + test=Compare( + left=Name(id='offset', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='flex', ctx=Load()), + attr='children', + ctx=Load())], + keywords=[])])), + Assign( + targets=[ + Name(id='new_node', ctx=Store())], + value=Call( + func=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='wrapped', ctx=Load())], + keywords=[]), + args=[], + keywords=[ + keyword( + value=Name(id='arguments', ctx=Load()))]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='wrapped', ctx=Load()), + Name(id='Reference', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Constant(value=1), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='flex', ctx=Load()), + attr='children', + ctx=Load())], + keywords=[])])), + Assign( + targets=[ + Name(id='new_node', ctx=Store())], + value=Call( + func=Name(id='Reference', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='identifier', + value=Attribute( + value=Name(id='wrapped', ctx=Load()), + attr='identifier', + ctx=Load())), + keyword( + arg='child', + value=Subscript( + value=Attribute( + value=Name(id='flex', ctx=Load()), + attr='children', + ctx=Load()), + slice=Constant(value=0), + ctx=Load()))]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='wrapped', ctx=Load()), + Name(id='Definition', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Compare( + left=Constant(value=1), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='flex', ctx=Load()), + attr='children', + ctx=Load())], + keywords=[])])), + Assign( + targets=[ + Name(id='new_node', ctx=Store())], + value=Call( + func=Name(id='Definition', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='identifier', + value=Attribute( + value=Name(id='wrapped', ctx=Load()), + attr='identifier', + ctx=Load())), + keyword( + arg='specifier', + value=Attribute( + value=Name(id='wrapped', ctx=Load()), + attr='specifier', + ctx=Load())), + keyword( + arg='child', + value=Subscript( + value=Attribute( + value=Name(id='flex', ctx=Load()), + attr='children', + ctx=Load()), + slice=Constant(value=0), + ctx=Load()))]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='wrapped', ctx=Load()), + Name(id='ListNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='new_node', ctx=Store())], + value=Call( + func=Name(id='ListNode', ctx=Load()), + args=[ + Attribute( + value=Name(id='flex', ctx=Load()), + attr='children', + ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='wrapped', ctx=Load()), + Attribute( + value=Name(id='mistletoe', ctx=Load()), + attr='MarkdownNode', + ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='new_node', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='mistletoe', ctx=Load()), + attr='MarkdownNode', + ctx=Load()), + args=[ + Attribute( + value=Name(id='wrapped', ctx=Load()), + attr='token', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='new_node', ctx=Load()), + attr='_children', + ctx=Store())], + value=Call( + func=Name(id='list', ctx=Load()), + args=[ + Attribute( + value=Name(id='flex', ctx=Load()), + attr='children', + ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='wrapped', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Transcribed', + ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='new_node', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Transcribed', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='_children', + value=Call( + func=Name(id='list', ctx=Load()), + args=[ + Attribute( + value=Name(id='flex', ctx=Load()), + attr='children', + ctx=Load())], + keywords=[]))]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='wrapped', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Line', + ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='new_node', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Line', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='number', + value=Attribute( + value=Name(id='wrapped', ctx=Load()), + attr='number', + ctx=Load())), + keyword( + arg='_children', + value=Call( + func=Name(id='list', ctx=Load()), + args=[ + Attribute( + value=Name(id='flex', ctx=Load()), + attr='children', + ctx=Load())], + keywords=[]))]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='wrapped', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Highlight', + ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='new_node', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Highlight', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='highlights', + value=Call( + func=Name(id='list', ctx=Load()), + args=[ + Attribute( + value=Name(id='wrapped', ctx=Load()), + attr='highlights', + ctx=Load())], + keywords=[])), + keyword( + arg='_children', + value=Call( + func=Name(id='list', ctx=Load()), + args=[ + Attribute( + value=Name(id='flex', ctx=Load()), + attr='children', + ctx=Load())], + keywords=[]))]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='wrapped', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Text', + ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='new_node', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Text', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='text', + value=Attribute( + value=Name(id='wrapped', ctx=Load()), + attr='text', + ctx=Load()))]))], + orelse=[ + Raise( + exc=Call( + func=Name(id='NotImplementedError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='hardening '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='wrapped', ctx=Load())], + keywords=[]), + conversion=-1)])], + keywords=[]))])])])])])])])])]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_stack', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='new_node', ctx=Load())], + keywords=[])), + Try( + body=[ + Assign( + targets=[ + Name(id='parent', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=2)), + ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='IndexError', ctx=Load()), + body=[ + Return( + value=Attribute( + value=Name(id='Visit', ctx=Load()), + attr='TraverseChildren', + ctx=Load()))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='parent', ctx=Load()), + attr='replace_child', + ctx=Load()), + args=[ + Name(id='flex', ctx=Load()), + Name(id='new_node', ctx=Load())], + keywords=[])), + Return( + value=Attribute( + value=Name(id='Visit', ctx=Load()), + attr='TraverseChildren', + ctx=Load()))], + decorator_list=[], + returns=Name(id='Visit', ctx=Load())), + FunctionDef( + name='exit', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='node', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_stack', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='_DoccApply', + bases=[ + Subscript( + value=Name(id='Apply', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load())], + keywords=[], + body=[ + ClassDef( + name='ApplyNode', + bases=[ + Name(id='Node', ctx=Load())], + keywords=[], + body=[ + Assign( + targets=[ + Name(id='__slots__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='children')], + ctx=Load())), + AnnAssign( + target=Name(id='children', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='children', + ctx=Store())], + value=List(elts=[], ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='add', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='node', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='children', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='replace_child', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='old', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='new', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='children', + ctx=Store())], + value=ListComp( + elt=IfExp( + test=Compare( + left=Name(id='x', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='old', ctx=Load())]), + body=Name(id='new', ctx=Load()), + orelse=Name(id='x', ctx=Load())), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Attribute( + value=Name(id='self', ctx=Load()), + attr='children', + ctx=Load()), + ifs=[], + is_async=0)]))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='FlexNode', + bases=[ + Name(id='ApplyNode', ctx=Load())], + keywords=[], + body=[ + Assign( + targets=[ + Name(id='__slots__', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='node')], + ctx=Load())), + AnnAssign( + target=Name(id='node', ctx=Store()), + annotation=Name(id='Node', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='node', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='node', + ctx=Store())], + value=Name(id='node', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='__repr__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Return( + value=JoinedStr( + values=[ + Constant(value='FlexNode(node='), + FormattedValue( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='node', + ctx=Load()), + conversion=114), + Constant(value=', ...)')]))], + decorator_list=[], + returns=Name(id='str', ctx=Load()))], + decorator_list=[]), + AnnAssign( + target=Name(id='SUPPORTS_BLOCKS', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Tuple( + elts=[ + Name(id='ListNode', ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Line', + ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Transcribed', + ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Fragment', + ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='Highlight', + ctx=Load()), + Attribute( + value=Name(id='verbatim', ctx=Load()), + attr='VerbatimNode', + ctx=Load()), + Attribute( + value=Name(id='html', ctx=Load()), + attr='HTMLTag', + ctx=Load()), + Attribute( + value=Name(id='html', ctx=Load()), + attr='HTMLRoot', + ctx=Load()), + Attribute( + value=Name(id='mistletoe', ctx=Load()), + attr='MarkdownNode', + ctx=Load())], + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='before_name', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='after_name', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='ApplyNode', ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='root', ctx=Store()), + annotation=Name(id='ApplyNode', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='before_name', + annotation=Name(id='str', ctx=Load())), + arg( + arg='before', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='after_name', + annotation=Name(id='str', ctx=Load())), + arg( + arg='after', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Call( + func=Name(id='_DoccAdapter', ctx=Load()), + args=[], + keywords=[]), + Name(id='before', ctx=Load()), + Name(id='after', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='before_name', + ctx=Store())], + value=Name(id='before_name', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='after_name', + ctx=Store())], + value=Name(id='after_name', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='stack', + ctx=Store())], + value=List(elts=[], ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='root', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='_DoccApply', ctx=Load()), + attr='ApplyNode', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='apply', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='operations', + annotation=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='Operation', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assert( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='self', ctx=Load()), + attr='stack', + ctx=Load()))), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='root', + ctx=Load()), + attr='children', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[])), + Try( + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='stack', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='root', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='apply', + ctx=Load()), + args=[ + Name(id='operations', ctx=Load())], + keywords=[]))], + handlers=[], + orelse=[], + finalbody=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='stack', + ctx=Load()), + attr='clear', + ctx=Load()), + args=[], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='replace', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='befores', + annotation=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load())), + arg( + arg='afters', + annotation=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='parent', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())), + If( + test=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_supports_blocks', + ctx=Load()), + args=[ + Name(id='parent', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='parent', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='DiffNode', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='before_name', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='before_name', + ctx=Load())), + keyword( + arg='before', + value=Call( + func=Name(id='BeforeNode', ctx=Load()), + args=[ + Call( + func=Name(id='ListNode', ctx=Load()), + args=[ + Call( + func=Name(id='list', ctx=Load()), + args=[ + Name(id='befores', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + keyword( + arg='after_name', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='after_name', + ctx=Load())), + keyword( + arg='after', + value=Call( + func=Name(id='AfterNode', ctx=Load()), + args=[ + Call( + func=Name(id='ListNode', ctx=Load()), + args=[ + Call( + func=Name(id='list', ctx=Load()), + args=[ + Name(id='afters', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))])], + keywords=[]))], + orelse=[ + For( + target=Tuple( + elts=[ + Name(id='before', ctx=Store()), + Name(id='after', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='zip_longest', ctx=Load()), + args=[ + Name(id='befores', ctx=Load()), + Name(id='afters', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='parent', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='DiffNode', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='before_name', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='before_name', + ctx=Load())), + keyword( + arg='before', + value=IfExp( + test=Name(id='before', ctx=Load()), + body=Call( + func=Name(id='BeforeNode', ctx=Load()), + args=[ + Name(id='before', ctx=Load())], + keywords=[]), + orelse=Call( + func=Name(id='BlankNode', ctx=Load()), + args=[], + keywords=[]))), + keyword( + arg='after_name', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='after_name', + ctx=Load())), + keyword( + arg='after', + value=IfExp( + test=Name(id='after', ctx=Load()), + body=Call( + func=Name(id='AfterNode', ctx=Load()), + args=[ + Name(id='after', ctx=Load())], + keywords=[]), + orelse=Call( + func=Name(id='BlankNode', ctx=Load()), + args=[], + keywords=[])))])], + keywords=[]))], + orelse=[])])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='delete', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='befores', + annotation=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='parent', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())), + If( + test=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_supports_blocks', + ctx=Load()), + args=[ + Name(id='parent', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='parent', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='DiffNode', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='before_name', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='before_name', + ctx=Load())), + keyword( + arg='before', + value=Call( + func=Name(id='BeforeNode', ctx=Load()), + args=[ + Call( + func=Name(id='ListNode', ctx=Load()), + args=[ + Call( + func=Name(id='list', ctx=Load()), + args=[ + Name(id='befores', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + keyword( + arg='after_name', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='after_name', + ctx=Load())), + keyword( + arg='after', + value=Call( + func=Name(id='BlankNode', ctx=Load()), + args=[], + keywords=[]))])], + keywords=[]))], + orelse=[ + For( + target=Name(id='before', ctx=Store()), + iter=Name(id='befores', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='parent', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='DiffNode', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='before_name', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='before_name', + ctx=Load())), + keyword( + arg='before', + value=Call( + func=Name(id='BeforeNode', ctx=Load()), + args=[ + Name(id='before', ctx=Load())], + keywords=[])), + keyword( + arg='after_name', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='after_name', + ctx=Load())), + keyword( + arg='after', + value=Call( + func=Name(id='BlankNode', ctx=Load()), + args=[], + keywords=[]))])], + keywords=[]))], + orelse=[])])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='insert', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='afters', + annotation=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='parent', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())), + If( + test=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_supports_blocks', + ctx=Load()), + args=[ + Name(id='parent', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='parent', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='DiffNode', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='before_name', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='before_name', + ctx=Load())), + keyword( + arg='before', + value=Call( + func=Name(id='BlankNode', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='after_name', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='after_name', + ctx=Load())), + keyword( + arg='after', + value=Call( + func=Name(id='AfterNode', ctx=Load()), + args=[ + Call( + func=Name(id='ListNode', ctx=Load()), + args=[ + Call( + func=Name(id='list', ctx=Load()), + args=[ + Name(id='afters', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))])], + keywords=[]))], + orelse=[ + For( + target=Name(id='after', ctx=Store()), + iter=Name(id='afters', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='parent', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='DiffNode', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='before_name', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='before_name', + ctx=Load())), + keyword( + arg='before', + value=Call( + func=Name(id='BlankNode', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='after_name', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='after_name', + ctx=Load())), + keyword( + arg='after', + value=Call( + func=Name(id='AfterNode', ctx=Load()), + args=[ + Name(id='after', ctx=Load())], + keywords=[]))])], + keywords=[]))], + orelse=[])])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='equal', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='before', + annotation=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load())), + arg( + arg='after', + annotation=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='parent', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())), + For( + target=Name(id='node', ctx=Store()), + iter=Name(id='after', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='parent', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='descend', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='before', + annotation=Name(id='Node', ctx=Load())), + arg( + arg='after', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='parent', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())), + Assign( + targets=[ + Name(id='node', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='_DoccApply', ctx=Load()), + attr='FlexNode', + ctx=Load()), + args=[ + Name(id='after', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parent', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='stack', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='ascend', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='stack', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='output', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assert( + test=Compare( + left=Constant(value=1), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='root', + ctx=Load()), + attr='children', + ctx=Load())], + keywords=[])])), + Return( + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='root', + ctx=Load()), + attr='children', + ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + decorator_list=[], + returns=Name(id='Node', ctx=Load())), + FunctionDef( + name='_supports_blocks', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Constant(value='_DoccApply'), + ctx=Load())), + arg( + arg='node', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='candidate', ctx=Store())], + value=Name(id='node', ctx=Load())), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Attribute( + value=Name(id='cls', ctx=Load()), + attr='FlexNode', + ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='candidate', ctx=Store())], + value=Attribute( + value=Name(id='node', ctx=Load()), + attr='node', + ctx=Load()))], + orelse=[]), + Return( + value=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='candidate', ctx=Load()), + Attribute( + value=Name(id='cls', ctx=Load()), + attr='SUPPORTS_BLOCKS', + ctx=Load())], + keywords=[]))], + decorator_list=[ + Name(id='classmethod', ctx=Load())], + returns=Name(id='bool', ctx=Load()))], + decorator_list=[]), + ClassDef( + name='MinimizeDiffsTransform', + bases=[ + Name(id='Transform', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Move `DiffNode` nodes as far down the tree as reasonably possible.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='settings', + annotation=Name(id='PluginSettings', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='transform', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='context', + annotation=Name(id='Context', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Apply the transformation to the given document.\n ')), + Assign( + targets=[ + Name(id='visitor', ctx=Store())], + value=Call( + func=Name(id='_MinimizeDiffsVisitor', ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Subscript( + value=Name(id='context', ctx=Load()), + slice=Name(id='Document', ctx=Load()), + ctx=Load()), + attr='root', + ctx=Load()), + attr='visit', + ctx=Load()), + args=[ + Name(id='visitor', ctx=Load())], + keywords=[])), + Assert( + test=Compare( + left=Attribute( + value=Name(id='visitor', ctx=Load()), + attr='root', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Attribute( + value=Subscript( + value=Name(id='context', ctx=Load()), + slice=Name(id='Document', ctx=Load()), + ctx=Load()), + attr='root', + ctx=Store())], + value=Attribute( + value=Name(id='visitor', ctx=Load()), + attr='root', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='_MinimizeDiffsVisitor', + bases=[ + Name(id='Visitor', ctx=Load())], + keywords=[], + body=[ + AnnAssign( + target=Name(id='root', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_stack', ctx=Store()), + annotation=Subscript( + value=Name(id='Final', ctx=Load()), + slice=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Node', ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_stack', + ctx=Store())], + value=List(elts=[], ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='root', + ctx=Store())], + value=Constant(value=None))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='enter', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='node', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_stack', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='root', + ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='root', + ctx=Store())], + value=Name(id='node', ctx=Load()))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='DiffNode', ctx=Load())], + keywords=[])), + body=[ + Return( + value=Attribute( + value=Name(id='Visit', ctx=Load()), + attr='TraverseChildren', + ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='before', ctx=Store())], + value=Attribute( + value=Name(id='node', ctx=Load()), + attr='before', + ctx=Load())), + Assign( + targets=[ + Name(id='after', ctx=Store())], + value=Attribute( + value=Name(id='node', ctx=Load()), + attr='after', + ctx=Load())), + If( + test=Name(id='before', ctx=Load()), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='before', ctx=Load()), + Name(id='BeforeNode', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='before', ctx=Store())], + value=Attribute( + value=Name(id='before', ctx=Load()), + attr='child', + ctx=Load()))], + orelse=[]), + If( + test=Name(id='after', ctx=Load()), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='after', ctx=Load()), + Name(id='AfterNode', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='after', ctx=Store())], + value=Attribute( + value=Name(id='after', ctx=Load()), + attr='child', + ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='adapter', ctx=Store())], + value=Call( + func=Name(id='_DoccAdapter', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='matcher', ctx=Store())], + value=Call( + func=Name(id='TreeMatcher', ctx=Load()), + args=[ + Name(id='adapter', ctx=Load()), + Name(id='before', ctx=Load()), + Name(id='after', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='operations', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='matcher', ctx=Load()), + attr='compute_operations', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='apply', ctx=Store())], + value=Call( + func=Name(id='_DoccApply', ctx=Load()), + args=[ + Attribute( + value=Name(id='node', ctx=Load()), + attr='before_name', + ctx=Load()), + Name(id='before', ctx=Load()), + Attribute( + value=Name(id='node', ctx=Load()), + attr='after_name', + ctx=Load()), + Name(id='after', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='apply', ctx=Load()), + attr='apply', + ctx=Load()), + args=[ + Name(id='operations', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='apply', ctx=Load()), + attr='root', + ctx=Load()), + attr='visit', + ctx=Load()), + args=[ + Call( + func=Name(id='_HardenVisitor', ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='apply', ctx=Load()), + attr='output', + ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=Constant(value=1), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_stack', + ctx=Load())], + keywords=[])]), + body=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_stack', + ctx=Load()), + slice=Constant(value=0), + ctx=Store())], + value=Name(id='output', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='root', + ctx=Store())], + value=Name(id='output', ctx=Load()))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=2)), + ctx=Load()), + attr='replace_child', + ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='output', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_stack', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Store())], + value=Name(id='output', ctx=Load()))]), + Return( + value=Attribute( + value=Name(id='Visit', ctx=Load()), + attr='SkipChildren', + ctx=Load()))], + decorator_list=[], + returns=Name(id='Visit', ctx=Load())), + FunctionDef( + name='exit', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='node', + annotation=Name(id='Node', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_stack', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + FunctionDef( + name='render_diff', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='context', + annotation=Name(id='object', ctx=Load())), + arg( + arg='parent', + annotation=Name(id='object', ctx=Load())), + arg( + arg='diff', + annotation=Name(id='object', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Render a DiffNode.\n ')), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='diff', ctx=Load()), + Name(id='DiffNode', ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='parent', ctx=Load()), + Tuple( + elts=[ + Attribute( + value=Name(id='html', ctx=Load()), + attr='HTMLTag', + ctx=Load()), + Attribute( + value=Name(id='html', ctx=Load()), + attr='HTMLRoot', + ctx=Load())], + ctx=Load())], + keywords=[])), + AnnAssign( + target=Name(id='parent_', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Attribute( + value=Name(id='html', ctx=Load()), + attr='HTMLTag', + ctx=Load()), + Attribute( + value=Name(id='html', ctx=Load()), + attr='HTMLRoot', + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Name(id='parent', ctx=Load()), + simple=1), + If( + test=BoolOp( + op=And(), + values=[ + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='parent_', ctx=Load()), + Attribute( + value=Name(id='html', ctx=Load()), + attr='HTMLTag', + ctx=Load())], + keywords=[]), + Compare( + left=Attribute( + value=Name(id='parent_', ctx=Load()), + attr='tag_name', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='table')])]), + body=[ + Assign( + targets=[ + Name(id='tag', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='html', ctx=Load()), + attr='HTMLTag', + ctx=Load()), + args=[ + Constant(value='tbody'), + Dict( + keys=[ + Constant(value='class')], + values=[ + Constant(value='diff')])], + keywords=[]))], + orelse=[ + Return( + value=Name(id='parent_', ctx=Load()))]), + Expr( + value=Call( + func=Attribute( + value=Name(id='parent_', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='tag', ctx=Load())], + keywords=[])), + Return( + value=Name(id='tag', ctx=Load()))], + decorator_list=[], + returns=Attribute( + value=Name(id='html', ctx=Load()), + attr='RenderResult', + ctx=Load())), + FunctionDef( + name='render_before_after', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='context', + annotation=Name(id='object', ctx=Load())), + arg( + arg='parent', + annotation=Name(id='object', ctx=Load())), + arg( + arg='node_', + annotation=Name(id='object', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Render a BeforeNode or an AfterNode.\n ')), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node_', ctx=Load()), + Tuple( + elts=[ + Name(id='BeforeNode', ctx=Load()), + Name(id='AfterNode', ctx=Load())], + ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='parent', ctx=Load()), + Tuple( + elts=[ + Attribute( + value=Name(id='html', ctx=Load()), + attr='HTMLTag', + ctx=Load()), + Attribute( + value=Name(id='html', ctx=Load()), + attr='HTMLRoot', + ctx=Load())], + ctx=Load())], + keywords=[])), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='context', ctx=Load()), + Name(id='Context', ctx=Load())], + keywords=[])), + AnnAssign( + target=Name(id='node', ctx=Store()), + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='BeforeNode', ctx=Load()), + Name(id='AfterNode', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Name(id='node_', ctx=Load()), + simple=1), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='BeforeNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='tag_name', ctx=Store())], + value=Constant(value='del')), + Assign( + targets=[ + Name(id='css_class', ctx=Store())], + value=Constant(value='diff-before'))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='node', ctx=Load()), + Name(id='AfterNode', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='tag_name', ctx=Store())], + value=Constant(value='ins')), + Assign( + targets=[ + Name(id='css_class', ctx=Store())], + value=Constant(value='diff-after'))], + orelse=[ + Expr( + value=Call( + func=Name(id='assert_never', ctx=Load()), + args=[ + Name(id='node', ctx=Load())], + keywords=[]))])]), + If( + test=BoolOp( + op=And(), + values=[ + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='parent', ctx=Load()), + Attribute( + value=Name(id='html', ctx=Load()), + attr='HTMLTag', + ctx=Load())], + keywords=[]), + Compare( + left=Attribute( + value=Name(id='parent', ctx=Load()), + attr='tag_name', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='tbody')])]), + body=[ + Assign( + targets=[ + Name(id='visitor', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='html', ctx=Load()), + attr='HTMLVisitor', + ctx=Load()), + args=[ + Name(id='context', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='node', ctx=Load()), + attr='child', + ctx=Load()), + attr='visit', + ctx=Load()), + args=[ + Name(id='visitor', ctx=Load())], + keywords=[])), + For( + target=Name(id='child', ctx=Store()), + iter=Attribute( + value=Attribute( + value=Name(id='visitor', ctx=Load()), + attr='root', + ctx=Load()), + attr='children', + ctx=Load()), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='child', ctx=Load()), + Attribute( + value=Name(id='html', ctx=Load()), + attr='HTMLTag', + ctx=Load())], + keywords=[])), + Try( + body=[ + Assign( + targets=[ + Name(id='classes', ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='child', ctx=Load()), + attr='attributes', + ctx=Load()), + slice=Constant(value='class'), + ctx=Load())), + If( + test=Compare( + left=Name(id='classes', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='child', ctx=Load()), + attr='attributes', + ctx=Load()), + slice=Constant(value='class'), + ctx=Store())], + value=Name(id='css_class', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='child', ctx=Load()), + attr='attributes', + ctx=Load()), + slice=Constant(value='class'), + ctx=Store())], + value=BinOp( + left=BinOp( + left=Name(id='classes', ctx=Load()), + op=Add(), + right=Constant(value=' ')), + op=Add(), + right=Name(id='css_class', ctx=Load())))])], + handlers=[ + ExceptHandler( + type=Name(id='KeyError', ctx=Load()), + body=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='child', ctx=Load()), + attr='attributes', + ctx=Load()), + slice=Constant(value='class'), + ctx=Store())], + value=Name(id='css_class', ctx=Load()))])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='parent', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='child', ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Constant(value=None))], + orelse=[ + Assign( + targets=[ + Name(id='div', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='html', ctx=Load()), + attr='HTMLTag', + ctx=Load()), + args=[ + Name(id='tag_name', ctx=Load()), + Dict( + keys=[ + Constant(value='class')], + values=[ + Name(id='css_class', ctx=Load())])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parent', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='div', ctx=Load())], + keywords=[])), + Return( + value=Name(id='div', ctx=Load()))])], + decorator_list=[], + returns=Attribute( + value=Name(id='html', ctx=Load()), + attr='RenderResult', + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/docc.v b/coq/ethereum_spec_tools/docc.v new file mode 100644 index 0000000000..83f00199d0 --- /dev/null +++ b/coq/ethereum_spec_tools/docc.v @@ -0,0 +1,43 @@ +(* Generated *) +(* +Plugins for docc specific to the Ethereum execution specification. +*) + + +Definition pairwise (iterable : (* TODO type *)) : M (* TODO type *) := + (* + ABCDEFG --> AB BC CD DE EF FG + *) + (* TODO assignment *) + do* [[ M.get_local ~(| "next" |) ~(| + M.get_local ~(| "b" |), + tt + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition render_diff (context : object) (parent : object) (diff : object) : M (* TODO type *) := + (* + Render a DiffNode. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_local ~(| "parent_" |), "append" |) ~(| + M.get_local ~(| "tag" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition render_before_after (context : object) (parent : object) (node_ : object) : M (* TODO type *) := + (* + Render a BeforeNode or an AfterNode. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum_spec_tools/evm_tools/__init__.ast b/coq/ethereum_spec_tools/evm_tools/__init__.ast new file mode 100644 index 0000000000..586e06c3d8 --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/__init__.ast @@ -0,0 +1,498 @@ +Module( + body=[ + Expr( + value=Constant(value='\nDefines EVM tools for use in the Ethereum specification.\n')), + Import( + names=[ + alias(name='argparse')]), + Import( + names=[ + alias(name='subprocess')]), + Import( + names=[ + alias(name='sys')]), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='Sequence'), + alias(name='Text'), + alias(name='TextIO')], + level=0), + ImportFrom( + module='ethereum', + names=[ + alias(name='__version__')], + level=0), + ImportFrom( + module='b11r', + names=[ + alias(name='B11R'), + alias(name='b11r_arguments')], + level=1), + ImportFrom( + module='daemon', + names=[ + alias(name='Daemon'), + alias(name='daemon_arguments')], + level=1), + ImportFrom( + module='statetest', + names=[ + alias(name='StateTest'), + alias(name='state_test_arguments')], + level=1), + ImportFrom( + module='t8n', + names=[ + alias(name='T8N'), + alias(name='t8n_arguments')], + level=1), + ImportFrom( + module='utils', + names=[ + alias(name='get_supported_forks')], + level=1), + Assign( + targets=[ + Name(id='DESCRIPTION', ctx=Store())], + value=BinOp( + left=Constant(value='\nThis is the EVM tool for execution specs. The EVM tool\nprovides a few useful subcommands to facilitate testing\nat the EVM layer.\n\nPlease refer to the following link for more information:\nhttps://github.com/ethereum/go-ethereum/blob/master/cmd/evm/README.md\n\nYou can use this to run the following tools:\n 1. t8n: A stateless state transition utility.\n 2. b11r: The tool is used to assemble and seal full block rlps.\n\n\nThe following forks are supported:\n'), + op=Add(), + right=Call( + func=Attribute( + value=Constant(value='\n'), + attr='join', + ctx=Load()), + args=[ + Call( + func=Name(id='get_supported_forks', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))), + FunctionDef( + name='create_parser', + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a command-line argument parser for the evm tool.\n ')), + Assign( + targets=[ + Name(id='new_parser', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='ArgumentParser', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='description', + value=Name(id='DESCRIPTION', ctx=Load())), + keyword( + arg='formatter_class', + value=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='RawDescriptionHelpFormatter', + ctx=Load()))])), + Assign( + targets=[ + Name(id='commit_hash', ctx=Store())], + value=Call( + func=Name(id='get_git_commit_hash', ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='new_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='-v'), + Constant(value='--version')], + keywords=[ + keyword( + arg='action', + value=Constant(value='version')), + keyword( + arg='version', + value=JoinedStr( + values=[ + Constant(value='%(prog)s '), + FormattedValue( + value=Name(id='__version__', ctx=Load()), + conversion=-1), + Constant(value=' (Git commit: '), + FormattedValue( + value=Name(id='commit_hash', ctx=Load()), + conversion=-1), + Constant(value=')')])), + keyword( + arg='help', + value=Constant(value='Show the version of the tool.'))])), + Assign( + targets=[ + Name(id='subparsers', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='new_parser', ctx=Load()), + attr='add_subparsers', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='dest', + value=Constant(value='evm_tool'))])), + Expr( + value=Call( + func=Name(id='daemon_arguments', ctx=Load()), + args=[ + Name(id='subparsers', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='t8n_arguments', ctx=Load()), + args=[ + Name(id='subparsers', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='b11r_arguments', ctx=Load()), + args=[ + Name(id='subparsers', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='state_test_arguments', ctx=Load()), + args=[ + Name(id='subparsers', ctx=Load())], + keywords=[])), + Return( + value=Name(id='new_parser', ctx=Load()))], + decorator_list=[], + returns=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='ArgumentParser', + ctx=Load())), + FunctionDef( + name='get_git_commit_hash', + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value="\n Run the 'git rev-parse HEAD' command to get the commit hash\n ")), + Try( + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='subprocess', ctx=Load()), + attr='run', + ctx=Load()), + args=[ + List( + elts=[ + Constant(value='git'), + Constant(value='rev-parse'), + Constant(value='HEAD')], + ctx=Load())], + keywords=[ + keyword( + arg='stdout', + value=Attribute( + value=Name(id='subprocess', ctx=Load()), + attr='PIPE', + ctx=Load())), + keyword( + arg='stderr', + value=Attribute( + value=Name(id='subprocess', ctx=Load()), + attr='PIPE', + ctx=Load())), + keyword( + arg='text', + value=Constant(value=True)), + keyword( + arg='check', + value=Constant(value=True))])), + Assign( + targets=[ + Name(id='commit_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='result', ctx=Load()), + attr='stdout', + ctx=Load()), + attr='strip', + ctx=Load()), + args=[], + keywords=[])), + Return( + value=Name(id='commit_hash', ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='FileNotFoundError', ctx=Load()), + name='e', + body=[ + Return( + value=Call( + func=Name(id='str', ctx=Load()), + args=[ + Name(id='e', ctx=Load())], + keywords=[]))]), + ExceptHandler( + type=Attribute( + value=Name(id='subprocess', ctx=Load()), + attr='CalledProcessError', + ctx=Load()), + name='e', + body=[ + Return( + value=BinOp( + left=Constant(value='Error: '), + op=Add(), + right=Call( + func=Name(id='str', ctx=Load()), + args=[ + Name(id='e', ctx=Load())], + keywords=[])))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='str', ctx=Load())), + FunctionDef( + name='main', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='args', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Text', ctx=Load()), + ctx=Load()), + ctx=Load())), + arg( + arg='out_file', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='TextIO', ctx=Load()), + ctx=Load())), + arg( + arg='in_file', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='TextIO', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=None), + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='Run the tools based on the given options.')), + Assign( + targets=[ + Name(id='parser', ctx=Store())], + value=Call( + func=Name(id='create_parser', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='options', ctx=Store()), + Name(id='_', ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='parse_known_args', + ctx=Load()), + args=[ + Name(id='args', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='out_file', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='out_file', ctx=Store())], + value=Attribute( + value=Name(id='sys', ctx=Load()), + attr='stdout', + ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Name(id='in_file', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='in_file', ctx=Store())], + value=Attribute( + value=Name(id='sys', ctx=Load()), + attr='stdin', + ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='evm_tool', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='t8n')]), + body=[ + Assign( + targets=[ + Name(id='t8n_tool', ctx=Store())], + value=Call( + func=Name(id='T8N', ctx=Load()), + args=[ + Name(id='options', ctx=Load()), + Name(id='out_file', ctx=Load()), + Name(id='in_file', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Attribute( + value=Name(id='t8n_tool', ctx=Load()), + attr='run', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='evm_tool', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='b11r')]), + body=[ + Assign( + targets=[ + Name(id='b11r_tool', ctx=Store())], + value=Call( + func=Name(id='B11R', ctx=Load()), + args=[ + Name(id='options', ctx=Load()), + Name(id='out_file', ctx=Load()), + Name(id='in_file', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Attribute( + value=Name(id='b11r_tool', ctx=Load()), + attr='run', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='evm_tool', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='daemon')]), + body=[ + Assign( + targets=[ + Name(id='daemon', ctx=Store())], + value=Call( + func=Name(id='Daemon', ctx=Load()), + args=[ + Name(id='options', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Attribute( + value=Name(id='daemon', ctx=Load()), + attr='run', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='evm_tool', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='statetest')]), + body=[ + Assign( + targets=[ + Name(id='state_test', ctx=Store())], + value=Call( + func=Name(id='StateTest', ctx=Load()), + args=[ + Name(id='options', ctx=Load()), + Name(id='out_file', ctx=Load()), + Name(id='in_file', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Attribute( + value=Name(id='state_test', ctx=Load()), + attr='run', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='print_help', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='file', + value=Name(id='out_file', ctx=Load()))])), + Return( + value=Constant(value=0))])])])])], + decorator_list=[], + returns=Name(id='int', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/__init__.v b/coq/ethereum_spec_tools/evm_tools/__init__.v new file mode 100644 index 0000000000..b775271d00 --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/__init__.v @@ -0,0 +1,63 @@ +(* Generated *) +(* +Defines EVM tools for use in the Ethereum specification. +*) + + +Definition create_parser : M (* TODO type *) := + (* + Create a command-line argument parser for the evm tool. + *) + do* M.assign "new_parser" [[ + M.get_field ~(| M.get_local ~(| "argparse" |), "ArgumentParser" |) ~(| + + |) in + ]] in + do* M.assign "commit_hash" [[ + M.get_local ~(| "get_git_commit_hash" |) ~(| + + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "new_parser" |), "add_argument" |) ~(| + (* TODO constant *), + (* TODO constant *) + |) ]] in + do* M.assign "subparsers" [[ + M.get_field ~(| M.get_local ~(| "new_parser" |), "add_subparsers" |) ~(| + + |) in + ]] in + do* [[ M.get_local ~(| "daemon_arguments" |) ~(| + M.get_local ~(| "subparsers" |) + |) ]] in + do* [[ M.get_local ~(| "t8n_arguments" |) ~(| + M.get_local ~(| "subparsers" |) + |) ]] in + do* [[ M.get_local ~(| "b11r_arguments" |) ~(| + M.get_local ~(| "subparsers" |) + |) ]] in + do* [[ M.get_local ~(| "state_test_arguments" |) ~(| + M.get_local ~(| "subparsers" |) + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition get_git_commit_hash : M str := + (* + Run the 'git rev-parse HEAD' command to get the commit hash + *) + (* TODO statement *) + M.pure tt. + +Definition main (args : (* TODO type *)) (out_file : (* TODO type *)) (in_file : (* TODO type *)) : M int := + (*Run the tools based on the given options.*) + do* M.assign "parser" [[ + M.get_local ~(| "create_parser" |) ~(| + + |) in + ]] in + (* TODO assignment *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum_spec_tools/evm_tools/__main__.ast b/coq/ethereum_spec_tools/evm_tools/__main__.ast new file mode 100644 index 0000000000..7863ae466c --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/__main__.ast @@ -0,0 +1,24 @@ +Module( + body=[ + Expr( + value=Constant(value='Entrypoint for the `evm-tools` command-line tool.')), + Import( + names=[ + alias(name='sys')]), + ImportFrom( + names=[ + alias(name='main')], + level=1), + Expr( + value=Call( + func=Attribute( + value=Name(id='sys', ctx=Load()), + attr='exit', + ctx=Load()), + args=[ + Call( + func=Name(id='main', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/__main__.v b/coq/ethereum_spec_tools/evm_tools/__main__.v new file mode 100644 index 0000000000..1846727e2f --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/__main__.v @@ -0,0 +1,3 @@ +(* Generated *) +(*Entrypoint for the `evm-tools` command-line tool.*) + diff --git a/coq/ethereum_spec_tools/evm_tools/b11r/__init__.ast b/coq/ethereum_spec_tools/evm_tools/b11r/__init__.ast new file mode 100644 index 0000000000..674def743a --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/b11r/__init__.ast @@ -0,0 +1,727 @@ +Module( + body=[ + Expr( + value=Constant(value='\nCreate a block builder tool for the given fork.\n')), + Import( + names=[ + alias(name='argparse')]), + Import( + names=[ + alias(name='json')]), + ImportFrom( + module='typing', + names=[ + alias(name='Optional'), + alias(name='TextIO')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum', + names=[ + alias(name='rlp')], + level=0), + ImportFrom( + module='utils', + names=[ + alias(name='get_stream_logger')], + level=2), + ImportFrom( + module='b11r_types', + names=[ + alias(name='Body'), + alias(name='Header')], + level=1), + FunctionDef( + name='b11r_arguments', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='subparsers', + annotation=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='_SubParsersAction', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the arguments for the b11r tool subparser.\n ')), + Assign( + targets=[ + Name(id='b11r_parser', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='subparsers', ctx=Load()), + attr='add_parser', + ctx=Load()), + args=[ + Constant(value='b11r')], + keywords=[ + keyword( + arg='help', + value=Constant(value='This is the b11r tool.'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='b11r_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--input.header')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='input_header')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='default', + value=Constant(value='header.json'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='b11r_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--input.ommers')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='input_ommers')), + keyword( + arg='type', + value=Name(id='str', ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='b11r_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--input.txs')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='input_txs')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='default', + value=Constant(value='txs.rlp'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='b11r_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--input.withdrawals')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='input_withdrawals')), + keyword( + arg='type', + value=Name(id='str', ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='b11r_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--output.basedir')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='output_basedir')), + keyword( + arg='type', + value=Name(id='str', ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='b11r_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--output.block')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='output_block')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='default', + value=Constant(value='block.json'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='b11r_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--seal.clique')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='seal_clique')), + keyword( + arg='type', + value=Name(id='str', ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='b11r_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--seal.ethash')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='seal_ethash')), + keyword( + arg='type', + value=Name(id='bool', ctx=Load())), + keyword( + arg='default', + value=Constant(value=False))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='b11r_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--seal.ethash.dir')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='seal_ethash_dir')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='default', + value=Constant(value=None))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='b11r_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--seal.ethash.mode')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='seal_ethash_mode')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='default', + value=Constant(value='normal'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='b11r_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--verbosity')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='verbosity')), + keyword( + arg='type', + value=Name(id='int', ctx=Load())), + keyword( + arg='default', + value=Constant(value=3))]))], + decorator_list=[], + returns=Constant(value=None)), + ClassDef( + name='B11R', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Creates the b11r tool.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='options', + annotation=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='Namespace', + ctx=Load())), + arg( + arg='out_file', + annotation=Name(id='TextIO', ctx=Load())), + arg( + arg='in_file', + annotation=Name(id='TextIO', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Initializes the b11r tool.\n ')), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Store())], + value=Name(id='options', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='out_file', + ctx=Store())], + value=Name(id='out_file', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='in_file', + ctx=Store())], + value=Name(id='in_file', ctx=Load())), + If( + test=Compare( + left=Constant(value='stdin'), + ops=[ + In()], + comparators=[ + Tuple( + elts=[ + Attribute( + value=Name(id='options', ctx=Load()), + attr='input_header', + ctx=Load()), + Attribute( + value=Name(id='options', ctx=Load()), + attr='input_ommers', + ctx=Load()), + Attribute( + value=Name(id='options', ctx=Load()), + attr='input_txs', + ctx=Load())], + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='stdin', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='in_file', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='stdin', ctx=Store())], + value=Constant(value=None))]), + AnnAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='body', + ctx=Store()), + annotation=Name(id='Body', ctx=Load()), + value=Call( + func=Name(id='Body', ctx=Load()), + args=[ + Name(id='options', ctx=Load()), + Name(id='stdin', ctx=Load())], + keywords=[]), + simple=0), + AnnAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='header', + ctx=Store()), + annotation=Name(id='Header', ctx=Load()), + value=Call( + func=Name(id='Header', ctx=Load()), + args=[ + Name(id='options', ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='body', + ctx=Load()), + Name(id='stdin', ctx=Load())], + keywords=[]), + simple=0), + AnnAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_rlp', + ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='bytes', ctx=Load()), + ctx=Load()), + value=Constant(value=None), + simple=0), + AnnAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_hash', + ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes32', ctx=Load()), + ctx=Load()), + value=Constant(value=None), + simple=0), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='logger', + ctx=Store())], + value=Call( + func=Name(id='get_stream_logger', ctx=Load()), + args=[ + Constant(value='B11R')], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='build_block', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Builds the block.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='logger', + ctx=Load()), + attr='info', + ctx=Load()), + args=[ + Constant(value='Building the block...')], + keywords=[])), + Assign( + targets=[ + Name(id='header_to_list', ctx=Store())], + value=ListComp( + elt=Name(id='value', ctx=Load()), + generators=[ + comprehension( + target=Name(id='value', ctx=Store()), + iter=Call( + func=Attribute( + value=Call( + func=Name(id='vars', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[]), + attr='values', + ctx=Load()), + args=[], + keywords=[]), + ifs=[ + Compare( + left=Name(id='value', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])], + is_async=0)])), + Assign( + targets=[ + Name(id='block', ctx=Store())], + value=List( + elts=[ + Name(id='header_to_list', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='body', + ctx=Load()), + attr='transactions', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='body', + ctx=Load()), + attr='ommers', + ctx=Load())], + ctx=Load())), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='body', + ctx=Load()), + attr='withdrawals', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='block', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='body', + ctx=Load()), + attr='withdrawals', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_rlp', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_hash', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Name(id='header_to_list', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='run', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Runs the b11r tool.\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='build_block', + ctx=Load()), + args=[], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_rlp', + ctx=Load())), + UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_hash', + ctx=Load()))]), + body=[ + Raise( + exc=Call( + func=Name(id='ValueError', ctx=Load()), + args=[ + Constant(value='Cannot output result. Block RLP or block hash is not built.')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Dict( + keys=[ + Constant(value='rlp'), + Constant(value='hash')], + values=[ + BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_rlp', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[])), + BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_hash', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[]))])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='logger', + ctx=Load()), + attr='info', + ctx=Load()), + args=[ + Constant(value='Writing the result...')], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='output_block', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='stdout')]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dump', + ctx=Load()), + args=[ + Name(id='result', ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='out_file', + ctx=Load())], + keywords=[ + keyword( + arg='indent', + value=Constant(value=4))]))], + orelse=[ + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='open', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='output_block', + ctx=Load()), + Constant(value='w')], + keywords=[]), + optional_vars=Name(id='f', ctx=Store()))], + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dump', + ctx=Load()), + args=[ + Name(id='result', ctx=Load()), + Name(id='f', ctx=Load())], + keywords=[ + keyword( + arg='indent', + value=Constant(value=4))]))]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='logger', + ctx=Load()), + attr='info', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='The result has been written to '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='output_block', + ctx=Load()), + conversion=-1), + Constant(value='.')])], + keywords=[]))]), + Return( + value=Constant(value=0))], + decorator_list=[], + returns=Name(id='int', ctx=Load()))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/b11r/__init__.v b/coq/ethereum_spec_tools/evm_tools/b11r/__init__.v new file mode 100644 index 0000000000..28713e6c8d --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/b11r/__init__.v @@ -0,0 +1,49 @@ +(* Generated *) +(* +Create a block builder tool for the given fork. +*) + + +Definition b11r_arguments (subparsers : (* TODO type *)) : M unit := + (* + Adds the arguments for the b11r tool subparser. + *) + do* M.assign "b11r_parser" [[ + M.get_field ~(| subparsers, "add_parser" |) ~(| + (* TODO constant *) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "b11r_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "b11r_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "b11r_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "b11r_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "b11r_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "b11r_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "b11r_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "b11r_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "b11r_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "b11r_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "b11r_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + M.pure tt. diff --git a/coq/ethereum_spec_tools/evm_tools/b11r/b11r_types.ast b/coq/ethereum_spec_tools/evm_tools/b11r/b11r_types.ast new file mode 100644 index 0000000000..552577b6cd --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/b11r/b11r_types.ast @@ -0,0 +1,1006 @@ +Module( + body=[ + Expr( + value=Constant(value='\nDefine the types used by the b11r tool.\n')), + Import( + names=[ + alias(name='json')]), + ImportFrom( + module='typing', + names=[ + alias(name='Any'), + alias(name='List'), + alias(name='Optional'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes8'), + alias(name='Bytes20'), + alias(name='Bytes32'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum', + names=[ + alias(name='rlp')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes'), + alias(name='hex_to_bytes8')], + level=0), + ImportFrom( + module='utils', + names=[ + alias(name='parse_hex_or_int')], + level=2), + Assign( + targets=[ + Name(id='DEFAULT_TRIE_ROOT', ctx=Store())], + value=Constant(value='0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421')), + Assign( + targets=[ + Name(id='DEFAULT_COINBASE', ctx=Store())], + value=Constant(value='0x0000000000000000000000000000000000000000')), + ClassDef( + name='Body', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A class representing a block body.\n ')), + AnnAssign( + target=Name(id='transactions', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='Extended', + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='withdrawals', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U64', ctx=Load()), + Name(id='U64', ctx=Load()), + Name(id='Bytes20', ctx=Load()), + Name(id='Uint', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='options', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='stdin', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='input_txs', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='stdin')]), + body=[ + Assert( + test=Compare( + left=Name(id='stdin', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='txs_data', ctx=Store())], + value=Subscript( + value=Name(id='stdin', ctx=Load()), + slice=Constant(value='txs'), + ctx=Load()))], + orelse=[ + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='open', ctx=Load()), + args=[ + Attribute( + value=Name(id='options', ctx=Load()), + attr='input_txs', + ctx=Load())], + keywords=[]), + optional_vars=Name(id='f', ctx=Store()))], + body=[ + Assign( + targets=[ + Name(id='txs_data', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='f', ctx=Load())], + keywords=[]))])]), + If( + test=Compare( + left=Name(id='txs_data', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='')]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='transactions', + ctx=Store())], + value=List(elts=[], ctx=Load()))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='transactions', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode', + ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Name(id='txs_data', ctx=Load())], + keywords=[])], + keywords=[]))]), + If( + test=Compare( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='input_ommers', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='stdin')]), + body=[ + Assert( + test=Compare( + left=Name(id='stdin', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Try( + body=[ + Assign( + targets=[ + Name(id='ommers_data', ctx=Store())], + value=Subscript( + value=Name(id='stdin', ctx=Load()), + slice=Constant(value='ommers'), + ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='KeyError', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommers_data', ctx=Store())], + value=Subscript( + value=Name(id='stdin', ctx=Load()), + slice=Constant(value='uncles'), + ctx=Load()))])], + orelse=[], + finalbody=[])], + orelse=[ + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='open', ctx=Load()), + args=[ + Attribute( + value=Name(id='options', ctx=Load()), + attr='input_ommers', + ctx=Load())], + keywords=[]), + optional_vars=Name(id='f', ctx=Store()))], + body=[ + Assign( + targets=[ + Name(id='ommers_data', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='f', ctx=Load())], + keywords=[]))])]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='ommers', + ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers_data', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='decoded_ommer', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode', + ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Name(id='ommer', ctx=Load())], + keywords=[])], + keywords=[])), + Assert( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='decoded_ommer', ctx=Load()), + Name(id='bytes', ctx=Load())], + keywords=[]))), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='ommers', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Subscript( + value=Name(id='decoded_ommer', ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='input_withdrawals', + ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='withdrawals', + ctx=Store())], + value=Constant(value=None)), + Return()], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='input_withdrawals', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='stdin')]), + body=[ + Assert( + test=Compare( + left=Name(id='stdin', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='withdrawals_data', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='stdin', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='withdrawals'), + List(elts=[], ctx=Load())], + keywords=[]))], + orelse=[ + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='open', ctx=Load()), + args=[ + Attribute( + value=Name(id='options', ctx=Load()), + attr='input_withdrawals', + ctx=Load())], + keywords=[]), + optional_vars=Name(id='f', ctx=Store()))], + body=[ + Assign( + targets=[ + Name(id='withdrawals_data', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='f', ctx=Load())], + keywords=[]))])]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='withdrawals', + ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='wd', ctx=Store()), + iter=Name(id='withdrawals_data', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='withdrawals', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='wd', ctx=Load()), + slice=Constant(value='index'), + ctx=Load()), + Name(id='U64', ctx=Load())], + keywords=[]), + Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='wd', ctx=Load()), + slice=Constant(value='validatorIndex'), + ctx=Load()), + Name(id='U64', ctx=Load())], + keywords=[]), + Call( + func=Name(id='Bytes20', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='wd', ctx=Load()), + slice=Constant(value='address'), + ctx=Load())], + keywords=[])], + keywords=[]), + Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='wd', ctx=Load()), + slice=Constant(value='amount'), + ctx=Load()), + Name(id='Uint', ctx=Load())], + keywords=[])], + ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[])], + decorator_list=[]), + ClassDef( + name='Header', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A class representing a block header.\n ')), + AnnAssign( + target=Name(id='parent_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers_hash', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Bytes20', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transactions_root', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Hash32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Bytes256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='extra_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='mix_digest', ctx=Store()), + annotation=Name(id='Bytes32', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='nonce', ctx=Store()), + annotation=Name(id='Bytes8', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee_per_gas', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='withdrawals_root', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='options', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='body', + annotation=Name(id='Body', ctx=Load())), + arg( + arg='stdin', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='input_header', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='stdin')]), + body=[ + Assert( + test=Compare( + left=Name(id='stdin', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Subscript( + value=Name(id='stdin', ctx=Load()), + slice=Constant(value='header'), + ctx=Load()))], + orelse=[ + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='open', ctx=Load()), + args=[ + Attribute( + value=Name(id='options', ctx=Load()), + attr='input_header', + ctx=Load())], + keywords=[]), + optional_vars=Name(id='f', ctx=Store()))], + body=[ + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='f', ctx=Load())], + keywords=[]))])]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_hash', + ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='parentHash'), + ctx=Load())], + keywords=[])], + keywords=[])), + Try( + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='ommers_hash', + ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='ommersHash'), + ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='KeyError', ctx=Load()), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='ommers_hash', + ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Name(id='body', ctx=Load()), + attr='ommers', + ctx=Load())], + keywords=[])], + keywords=[]))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='coinbase', + ctx=Store())], + value=Call( + func=Name(id='Bytes20', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='miner'), + Name(id='DEFAULT_COINBASE', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='state_root', + ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='stateRoot'), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='transactions_root', + ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='transactionsRoot'), + Name(id='DEFAULT_TRIE_ROOT', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='receipt_root', + ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='receiptsRoot'), + Name(id='DEFAULT_TRIE_ROOT', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='bloom', + ctx=Store())], + value=Call( + func=Name(id='Bytes256', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='logsBloom'), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='difficulty', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='difficulty'), + Constant(value=0)], + keywords=[]), + Name(id='Uint', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='number', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='number'), + ctx=Load()), + Name(id='Uint', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='gas_limit', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='gasLimit'), + ctx=Load()), + Name(id='Uint', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='gas_used', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='gasUsed'), + ctx=Load()), + Name(id='Uint', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='timestamp', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='timestamp'), + ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='extra_data', + ctx=Store())], + value=Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='extraData'), + Constant(value='0x')], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='mix_digest', + ctx=Store())], + value=Call( + func=Name(id='Bytes32', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='mixHash'), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='nonce', + ctx=Store())], + value=Call( + func=Name(id='hex_to_bytes8', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='nonce'), + Constant(value='0x0000000000000000')], + keywords=[])], + keywords=[])), + Try( + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='base_fee_per_gas', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='baseFeePerGas'), + ctx=Load()), + Name(id='Uint', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='KeyError', ctx=Load()), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='base_fee_per_gas', + ctx=Store())], + value=Constant(value=None))])], + orelse=[], + finalbody=[]), + Try( + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='withdrawals_root', + ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='withdrawalsRoot'), + ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='base_fee_per_gas', + ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='base_fee_per_gas', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[])], + handlers=[ + ExceptHandler( + type=Name(id='KeyError', ctx=Load()), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='withdrawals_root', + ctx=Store())], + value=Constant(value=None))])], + orelse=[], + finalbody=[])], + decorator_list=[])], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/b11r/b11r_types.v b/coq/ethereum_spec_tools/evm_tools/b11r/b11r_types.v new file mode 100644 index 0000000000..f4d0e6f546 --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/b11r/b11r_types.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Define the types used by the b11r tool. +*) + diff --git a/coq/ethereum_spec_tools/evm_tools/daemon.ast b/coq/ethereum_spec_tools/evm_tools/daemon.ast new file mode 100644 index 0000000000..3d8b4918d9 --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/daemon.ast @@ -0,0 +1,897 @@ +Module( + body=[ + Expr( + value=Constant(value='\nRun ethereum-spec-evm as a daemon.\n')), + Import( + names=[ + alias(name='argparse')]), + Import( + names=[ + alias(name='json')]), + Import( + names=[ + alias(name='os.path')]), + Import( + names=[ + alias(name='socketserver')]), + Import( + names=[ + alias(name='time')]), + ImportFrom( + module='http.server', + names=[ + alias(name='BaseHTTPRequestHandler')], + level=0), + ImportFrom( + module='io', + names=[ + alias(name='StringIO'), + alias(name='TextIOWrapper')], + level=0), + ImportFrom( + module='socket', + names=[ + alias(name='socket')], + level=0), + ImportFrom( + module='threading', + names=[ + alias(name='Thread')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Any'), + alias(name='Tuple'), + alias(name='Union')], + level=0), + ImportFrom( + module='urllib.parse', + names=[ + alias(name='parse_qs'), + alias(name='urlparse')], + level=0), + FunctionDef( + name='daemon_arguments', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='subparsers', + annotation=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='_SubParsersAction', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the arguments for the daemon tool subparser.\n ')), + Assign( + targets=[ + Name(id='parser', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='subparsers', ctx=Load()), + attr='add_parser', + ctx=Load()), + args=[ + Constant(value='daemon')], + keywords=[ + keyword( + arg='help', + value=Constant(value='Spawn t8n as a daemon'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--uds')], + keywords=[ + keyword( + arg='help', + value=Constant(value='Unix domain socket path'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--timeout')], + keywords=[ + keyword( + arg='help', + value=Constant(value='Timeout to shutdown daemon if there are not requests (0 for no timeout)')), + keyword( + arg='type', + value=Name(id='int', ctx=Load()))]))], + decorator_list=[], + returns=Constant(value=None)), + ClassDef( + name='_EvmToolHandler', + bases=[ + Name(id='BaseHTTPRequestHandler', ctx=Load())], + keywords=[], + body=[ + FunctionDef( + name='log_request', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=BinOp( + left=Name(id='int', ctx=Load()), + op=BitOr(), + right=Name(id='str', ctx=Load()))), + arg( + arg='size', + annotation=BinOp( + left=Name(id='int', ctx=Load()), + op=BitOr(), + right=Name(id='str', ctx=Load())))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value='-'), + Constant(value='-')]), + body=[ + Expr( + value=Constant(value="Don't log requests")), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='do_POST', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + ImportFrom( + names=[ + alias(name='main')], + level=1), + Assign( + targets=[ + Name(id='content_length', ctx=Store())], + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='headers', + ctx=Load()), + slice=Constant(value='Content-Length'), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='content_bytes', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='rfile', + ctx=Load()), + attr='read', + ctx=Load()), + args=[ + Name(id='content_length', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='content', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='loads', + ctx=Load()), + args=[ + Name(id='content_bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='input_string', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dumps', + ctx=Load()), + args=[ + Subscript( + value=Name(id='content', ctx=Load()), + slice=Constant(value='input'), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='input', ctx=Store())], + value=Call( + func=Name(id='StringIO', ctx=Load()), + args=[ + Name(id='input_string', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='args', ctx=Store())], + value=List( + elts=[ + Constant(value='t8n'), + Constant(value='--input.env=stdin'), + Constant(value='--input.alloc=stdin'), + Constant(value='--input.txs=stdin'), + Constant(value='--output.result=stdout'), + Constant(value='--output.body=stdout'), + Constant(value='--output.alloc=stdout'), + JoinedStr( + values=[ + Constant(value='--state.fork='), + FormattedValue( + value=Subscript( + value=Subscript( + value=Name(id='content', ctx=Load()), + slice=Constant(value='state'), + ctx=Load()), + slice=Constant(value='fork'), + ctx=Load()), + conversion=-1)]), + JoinedStr( + values=[ + Constant(value='--state.chainid='), + FormattedValue( + value=Subscript( + value=Subscript( + value=Name(id='content', ctx=Load()), + slice=Constant(value='state'), + ctx=Load()), + slice=Constant(value='chainid'), + ctx=Load()), + conversion=-1)]), + JoinedStr( + values=[ + Constant(value='--state.reward='), + FormattedValue( + value=Subscript( + value=Subscript( + value=Name(id='content', ctx=Load()), + slice=Constant(value='state'), + ctx=Load()), + slice=Constant(value='reward'), + ctx=Load()), + conversion=-1)])], + ctx=Load())), + Assign( + targets=[ + Name(id='query_string', ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='urlparse', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='path', + ctx=Load())], + keywords=[]), + attr='query', + ctx=Load())), + If( + test=Name(id='query_string', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='query', ctx=Store())], + value=Call( + func=Name(id='parse_qs', ctx=Load()), + args=[ + Name(id='query_string', ctx=Load())], + keywords=[ + keyword( + arg='keep_blank_values', + value=Constant(value=True)), + keyword( + arg='strict_parsing', + value=Constant(value=True)), + keyword( + arg='errors', + value=Constant(value='strict'))])), + AugAssign( + target=Name(id='args', ctx=Store()), + op=Add(), + value=Call( + func=Attribute( + value=Name(id='query', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='arg'), + List(elts=[], ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='send_response', + ctx=Load()), + args=[ + Constant(value=200)], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='send_header', + ctx=Load()), + args=[ + Constant(value='Content-type'), + Constant(value='application/octet-stream')], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='end_headers', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='out_wrapper', ctx=Store())], + value=Call( + func=Name(id='TextIOWrapper', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='wfile', + ctx=Load())], + keywords=[ + keyword( + arg='encoding', + value=Constant(value='utf-8'))])), + Expr( + value=Call( + func=Name(id='main', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='args', + value=Name(id='args', ctx=Load())), + keyword( + arg='out_file', + value=Name(id='out_wrapper', ctx=Load())), + keyword( + arg='in_file', + value=Name(id='input', ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='out_wrapper', ctx=Load()), + attr='flush', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='_UnixSocketHttpServer', + bases=[ + Attribute( + value=Name(id='socketserver', ctx=Load()), + attr='UnixStreamServer', + ctx=Load())], + keywords=[], + body=[ + AnnAssign( + target=Name(id='last_response', ctx=Store()), + annotation=Name(id='float', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='shutdown_timeout', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + vararg=arg( + arg='args', + annotation=Name(id='Any', ctx=Load())), + kwonlyargs=[ + arg( + arg='shutdown_timeout', + annotation=Name(id='int', ctx=Load()))], + kw_defaults=[ + None], + kwarg=arg( + arg='kwargs', + annotation=Name(id='Any', ctx=Load())), + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='shutdown_timeout', + ctx=Store())], + value=Name(id='shutdown_timeout', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='last_response', + ctx=Store())], + value=BinOp( + left=Call( + func=Attribute( + value=Name(id='time', ctx=Load()), + attr='monotonic', + ctx=Load()), + args=[], + keywords=[]), + op=Add(), + right=Constant(value=60.0))), + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Starred( + value=Name(id='args', ctx=Load()), + ctx=Load())], + keywords=[ + keyword( + value=Name(id='kwargs', ctx=Load()))]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_request', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Tuple( + elts=[ + Name(id='request', ctx=Store()), + Name(id='client_address', ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='get_request', + ctx=Load()), + args=[], + keywords=[])), + Return( + value=Tuple( + elts=[ + Name(id='request', ctx=Load()), + List( + elts=[ + Constant(value='local'), + Constant(value=0)], + ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Any', ctx=Load()), + Name(id='Any', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='finish_request', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='request', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='socket', ctx=Load()), + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='bytes', ctx=Load()), + Name(id='socket', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='client_address', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Try( + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='finish_request', + ctx=Load()), + args=[ + Name(id='request', ctx=Load()), + Name(id='client_address', ctx=Load())], + keywords=[]))], + handlers=[], + orelse=[], + finalbody=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='last_response', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='time', ctx=Load()), + attr='monotonic', + ctx=Load()), + args=[], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='check_timeout', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + While( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='shutdown_timeout', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='time', ctx=Load()), + attr='sleep', + ctx=Load()), + args=[ + Constant(value=11.0)], + keywords=[])), + Assign( + targets=[ + Name(id='now', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='time', ctx=Load()), + attr='monotonic', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='last_response', ctx=Store())], + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='last_response', + ctx=Load())), + If( + test=Compare( + left=Name(id='last_response', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='last_response', + ctx=Store())], + value=Name(id='now', ctx=Load()))], + orelse=[ + If( + test=Compare( + left=BinOp( + left=Name(id='now', ctx=Load()), + op=Sub(), + right=Name(id='last_response', ctx=Load())), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='float', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='shutdown_timeout', + ctx=Load())], + keywords=[])]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='shutdown', + ctx=Load()), + args=[], + keywords=[])), + Break()], + orelse=[])])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='Daemon', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Converts HTTP requests into ethereum-spec-evm calls.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='options', + annotation=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='Namespace', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='uds', + ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Try( + body=[ + ImportFrom( + module='platformdirs', + names=[ + alias(name='user_runtime_dir')], + level=0)], + handlers=[ + ExceptHandler( + type=Name(id='ImportError', ctx=Load()), + name='e', + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value='Missing plaformdirs dependency (try installing ethereum[tools] extra)')], + keywords=[]), + cause=Name(id='e', ctx=Load()))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='runtime_dir', ctx=Store())], + value=Call( + func=Name(id='user_runtime_dir', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='appname', + value=Constant(value='ethereum-spec-evm')), + keyword( + arg='appauthor', + value=Constant(value='org.ethereum')), + keyword( + arg='ensure_exists', + value=Constant(value=True))])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='uds', + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='os', ctx=Load()), + attr='path', + ctx=Load()), + attr='join', + ctx=Load()), + args=[ + Name(id='runtime_dir', ctx=Load()), + Constant(value='daemon.sock')], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='uds', + ctx=Store())], + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='uds', + ctx=Load()))]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='timeout', + ctx=Store())], + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='timeout', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='_run', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Try( + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='os', ctx=Load()), + attr='remove', + ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='uds', + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='IOError', ctx=Load()), + body=[ + Pass()])], + orelse=[], + finalbody=[]), + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='_UnixSocketHttpServer', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='uds', + ctx=Load()), + Name(id='_EvmToolHandler', ctx=Load())], + keywords=[ + keyword( + arg='shutdown_timeout', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='timeout', + ctx=Load()))]), + optional_vars=Name(id='server', ctx=Store()))], + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='server', ctx=Load()), + attr='timeout', + ctx=Store())], + value=Constant(value=7.0)), + Assign( + targets=[ + Name(id='timer', ctx=Store())], + value=Call( + func=Name(id='Thread', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='target', + value=Attribute( + value=Name(id='server', ctx=Load()), + attr='check_timeout', + ctx=Load())), + keyword( + arg='daemon', + value=Constant(value=True))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='timer', ctx=Load()), + attr='start', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='server', ctx=Load()), + attr='serve_forever', + ctx=Load()), + args=[], + keywords=[]))]), + Return( + value=Constant(value=0))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='run', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Execute the tool.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_run', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load()))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/daemon.v b/coq/ethereum_spec_tools/evm_tools/daemon.v new file mode 100644 index 0000000000..0e0ad16c85 --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/daemon.v @@ -0,0 +1,22 @@ +(* Generated *) +(* +Run ethereum-spec-evm as a daemon. +*) + + +Definition daemon_arguments (subparsers : (* TODO type *)) : M unit := + (* + Adds the arguments for the daemon tool subparser. + *) + do* M.assign "parser" [[ + M.get_field ~(| subparsers, "add_parser" |) ~(| + (* TODO constant *) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + M.pure tt. diff --git a/coq/ethereum_spec_tools/evm_tools/loaders/__init__.ast b/coq/ethereum_spec_tools/evm_tools/loaders/__init__.ast new file mode 100644 index 0000000000..52e9f38145 --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/loaders/__init__.ast @@ -0,0 +1,5 @@ +Module( + body=[ + Expr( + value=Constant(value='\nLoaders for json fixtures and fork code.\n'))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/loaders/__init__.v b/coq/ethereum_spec_tools/evm_tools/loaders/__init__.v new file mode 100644 index 0000000000..a7dc7dcf7f --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/loaders/__init__.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Loaders for json fixtures and fork code. +*) + diff --git a/coq/ethereum_spec_tools/evm_tools/loaders/fixture_loader.ast b/coq/ethereum_spec_tools/evm_tools/loaders/fixture_loader.ast new file mode 100644 index 0000000000..e0e5c041db --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/loaders/fixture_loader.ast @@ -0,0 +1,1203 @@ +Module( + body=[ + Expr( + value=Constant(value='\nDefines Load class for loading json fixtures for the evm\ntools (t8n, b11r, etc.) as well as the execution specs\ntesting framework.\n')), + ImportFrom( + module='abc', + names=[ + alias(name='ABC'), + alias(name='abstractmethod')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Any'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256')], + level=0), + ImportFrom( + module='ethereum', + names=[ + alias(name='rlp')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes'), + alias(name='hex_to_bytes8'), + alias(name='hex_to_bytes32'), + alias(name='hex_to_hash'), + alias(name='hex_to_u64'), + alias(name='hex_to_u256'), + alias(name='hex_to_uint')], + level=0), + ImportFrom( + module='fork_loader', + names=[ + alias(name='ForkLoad')], + level=1), + ImportFrom( + module='transaction_loader', + names=[ + alias(name='TransactionLoad')], + level=1), + ClassDef( + name='BaseLoad', + bases=[ + Name(id='ABC', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='Base class for loading JSON fixtures')), + FunctionDef( + name='json_to_header', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='json_data', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Converts json header data to a header object')), + Raise( + exc=Call( + func=Name(id='NotImplementedError', ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[ + Name(id='abstractmethod', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='json_to_state', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='json_data', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Converts json state data to a state object')), + Raise( + exc=Call( + func=Name(id='NotImplementedError', ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[ + Name(id='abstractmethod', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='json_to_block', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='json_data', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Converts json block data to a list of blocks')), + Raise( + exc=Call( + func=Name(id='NotImplementedError', ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[ + Name(id='abstractmethod', ctx=Load())], + returns=Name(id='Any', ctx=Load()))], + decorator_list=[]), + ClassDef( + name='Load', + bases=[ + Name(id='BaseLoad', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='Class for loading json fixtures')), + AnnAssign( + target=Name(id='_network', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_fork_module', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='fork', ctx=Store()), + annotation=Name(id='ForkLoad', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='network', + annotation=Name(id='str', ctx=Load())), + arg( + arg='fork_module', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_network', + ctx=Store())], + value=Name(id='network', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_fork_module', + ctx=Store())], + value=Name(id='fork_module', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Store())], + value=Call( + func=Name(id='ForkLoad', ctx=Load()), + args=[ + Name(id='fork_module', ctx=Load())], + keywords=[]))], + decorator_list=[]), + FunctionDef( + name='json_to_state', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='raw', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Converts json state data to a state object')), + Assign( + targets=[ + Name(id='state', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='State', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='set_storage', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='set_storage', + ctx=Load())), + For( + target=Tuple( + elts=[ + Name(id='address_hex', ctx=Store()), + Name(id='account_state', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='address', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='hex_to_address', + ctx=Load()), + args=[ + Name(id='address_hex', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='account', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Account', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='nonce', + value=Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='account_state', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='nonce'), + Constant(value='0x0')], + keywords=[])], + keywords=[])), + keyword( + arg='balance', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='account_state', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='balance'), + Constant(value='0x0')], + keywords=[])], + keywords=[])], + keywords=[])), + keyword( + arg='code', + value=Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='account_state', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='code'), + Constant(value='')], + keywords=[])], + keywords=[]))])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='set_account', + ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='v', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='account_state', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='storage'), + Dict(keys=[], values=[])], + keywords=[]), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + Expr( + value=Call( + func=Name(id='set_storage', ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='address', ctx=Load()), + Call( + func=Name(id='hex_to_bytes32', ctx=Load()), + args=[ + Name(id='k', ctx=Load())], + keywords=[]), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes32', ctx=Load()), + args=[ + Name(id='v', ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Name(id='state', ctx=Load()))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='json_to_withdrawals', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='raw', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Converts json withdrawal data to a withdrawal object')), + Assign( + targets=[ + Name(id='parameters', ctx=Store())], + value=List( + elts=[ + Call( + func=Name(id='hex_to_u64', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='index')], + keywords=[])], + keywords=[]), + Call( + func=Name(id='hex_to_u64', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='validatorIndex')], + keywords=[])], + keywords=[]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='hex_to_address', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='address')], + keywords=[])], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='amount')], + keywords=[])], + keywords=[])], + ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Withdrawal', + ctx=Load()), + args=[ + Starred( + value=Name(id='parameters', ctx=Load()), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='json_to_block', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='json_block', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Converts json block data to a block object')), + If( + test=Compare( + left=Constant(value='rlp'), + ops=[ + In()], + comparators=[ + Name(id='json_block', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='block_rlp', ctx=Store())], + value=Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='json_block', ctx=Load()), + slice=Constant(value='rlp'), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Block', + ctx=Load()), + Name(id='block_rlp', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_header_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='rlp_hash', + ctx=Load()), + args=[ + Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load())], + keywords=[])), + Return( + value=Tuple( + elts=[ + Name(id='block', ctx=Load()), + Name(id='block_header_hash', ctx=Load()), + Name(id='block_rlp', ctx=Load())], + ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='header', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='json_to_header', + ctx=Load()), + args=[ + Subscript( + value=Name(id='json_block', ctx=Load()), + slice=Constant(value='blockHeader'), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='transactions', ctx=Store())], + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + GeneratorExp( + elt=Call( + func=Attribute( + value=Call( + func=Name(id='TransactionLoad', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load())], + keywords=[]), + attr='read', + ctx=Load()), + args=[], + keywords=[]), + generators=[ + comprehension( + target=Name(id='tx', ctx=Store()), + iter=Subscript( + value=Name(id='json_block', ctx=Load()), + slice=Constant(value='transactions'), + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[])), + Assign( + targets=[ + Name(id='uncles', ctx=Store())], + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + GeneratorExp( + elt=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='json_to_header', + ctx=Load()), + args=[ + Name(id='uncle', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='uncle', ctx=Store()), + iter=Subscript( + value=Name(id='json_block', ctx=Load()), + slice=Constant(value='uncleHeaders'), + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[])), + Assign( + targets=[ + Name(id='parameters', ctx=Store())], + value=List( + elts=[ + Name(id='header', ctx=Load()), + Name(id='transactions', ctx=Load()), + Name(id='uncles', ctx=Load())], + ctx=Load())), + If( + test=Compare( + left=Constant(value='withdrawals'), + ops=[ + In()], + comparators=[ + Name(id='json_block', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='withdrawals', ctx=Store())], + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + GeneratorExp( + elt=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='json_to_withdrawals', + ctx=Load()), + args=[ + Name(id='wd', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='wd', ctx=Store()), + iter=Subscript( + value=Name(id='json_block', ctx=Load()), + slice=Constant(value='withdrawals'), + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parameters', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='withdrawals', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='block', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Block', + ctx=Load()), + args=[ + Starred( + value=Name(id='parameters', ctx=Load()), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='block_header_hash', ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Subscript( + value=Name(id='json_block', ctx=Load()), + slice=Constant(value='blockHeader'), + ctx=Load()), + slice=Constant(value='hash'), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='block_rlp', ctx=Store())], + value=Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='json_block', ctx=Load()), + slice=Constant(value='rlp'), + ctx=Load())], + keywords=[])), + Return( + value=Tuple( + elts=[ + Name(id='block', ctx=Load()), + Name(id='block_header_hash', ctx=Load()), + Name(id='block_rlp', ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Any', ctx=Load()), + Name(id='Hash32', ctx=Load()), + Name(id='bytes', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='json_to_header', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='raw', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Converts json header data to a header object')), + Assign( + targets=[ + Name(id='parameters', ctx=Store())], + value=List( + elts=[ + Call( + func=Name(id='hex_to_hash', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='parentHash')], + keywords=[])], + keywords=[]), + Call( + func=Name(id='hex_to_hash', ctx=Load()), + args=[ + BoolOp( + op=Or(), + values=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='uncleHash')], + keywords=[]), + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='sha3Uncles')], + keywords=[])])], + keywords=[]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='hex_to_address', + ctx=Load()), + args=[ + BoolOp( + op=Or(), + values=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='coinbase')], + keywords=[]), + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='miner')], + keywords=[])])], + keywords=[]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='hex_to_root', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='stateRoot')], + keywords=[])], + keywords=[]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='hex_to_root', + ctx=Load()), + args=[ + BoolOp( + op=Or(), + values=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='transactionsTrie')], + keywords=[]), + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='transactionsRoot')], + keywords=[])])], + keywords=[]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='hex_to_root', + ctx=Load()), + args=[ + BoolOp( + op=Or(), + values=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='receiptTrie')], + keywords=[]), + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='receiptsRoot')], + keywords=[])])], + keywords=[]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Bloom', + ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + BoolOp( + op=Or(), + values=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='bloom')], + keywords=[]), + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='logsBloom')], + keywords=[])])], + keywords=[])], + keywords=[]), + Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='difficulty')], + keywords=[])], + keywords=[]), + Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='number')], + keywords=[])], + keywords=[]), + Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='gasLimit')], + keywords=[])], + keywords=[]), + Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='gasUsed')], + keywords=[])], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='timestamp')], + keywords=[])], + keywords=[]), + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='extraData')], + keywords=[])], + keywords=[]), + Call( + func=Name(id='hex_to_bytes32', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='mixHash')], + keywords=[])], + keywords=[]), + Call( + func=Name(id='hex_to_bytes8', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='nonce')], + keywords=[])], + keywords=[])], + ctx=Load())), + If( + test=Compare( + left=Constant(value='baseFeePerGas'), + ops=[ + In()], + comparators=[ + Name(id='raw', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='base_fee_per_gas', ctx=Store())], + value=Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='baseFeePerGas')], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parameters', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='base_fee_per_gas', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Constant(value='withdrawalsRoot'), + ops=[ + In()], + comparators=[ + Name(id='raw', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='withdrawals_root', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='hex_to_root', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='withdrawalsRoot')], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parameters', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='withdrawals_root', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Constant(value='excessBlobGas'), + ops=[ + In()], + comparators=[ + Name(id='raw', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='blob_gas_used', ctx=Store())], + value=Call( + func=Name(id='hex_to_u64', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='blobGasUsed')], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parameters', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='blob_gas_used', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='excess_blob_gas', ctx=Store())], + value=Call( + func=Name(id='hex_to_u64', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='excessBlobGas')], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parameters', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='excess_blob_gas', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='parent_beacon_block_root', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='hex_to_root', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='raw', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='parentBeaconBlockRoot')], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parameters', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='parent_beacon_block_root', ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Header', + ctx=Load()), + args=[ + Starred( + value=Name(id='parameters', ctx=Load()), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Any', ctx=Load()))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/loaders/fixture_loader.v b/coq/ethereum_spec_tools/evm_tools/loaders/fixture_loader.v new file mode 100644 index 0000000000..db0139d340 --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/loaders/fixture_loader.v @@ -0,0 +1,15 @@ +(* Generated *) +(* +Defines Load class for loading json fixtures for the evm +tools (t8n, b11r, etc.) as well as the execution specs +testing framework. +*) + +Require abc. +Require typing. +Require ethereum_types.numeric. +Require ethereum. +Require ethereum.crypto.hash. +Require ethereum.utils.hexadecimal. +Require ethereum_spec_tools.evm_tools.loaders.fork_loader. +Require ethereum_spec_tools.evm_tools.loaders.transaction_loader. diff --git a/coq/ethereum_spec_tools/evm_tools/loaders/fork_loader.ast b/coq/ethereum_spec_tools/evm_tools/loaders/fork_loader.ast new file mode 100644 index 0000000000..15b40d745b --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/loaders/fork_loader.ast @@ -0,0 +1,1636 @@ +Module( + body=[ + Expr( + value=Constant(value='\nLoader for code from the relevant fork.\n')), + Import( + names=[ + alias(name='importlib')]), + ImportFrom( + module='typing', + names=[ + alias(name='Any')], + level=0), + ImportFrom( + module='ethereum_spec_tools.forks', + names=[ + alias(name='Hardfork')], + level=0), + ClassDef( + name='ForkLoad', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Load the functions and classes from the relevant fork.\n ')), + AnnAssign( + target=Name(id='_fork_module', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_forks', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='fork_module', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_fork_module', + ctx=Store())], + value=Name(id='fork_module', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_forks', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Hardfork', ctx=Load()), + attr='discover', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[]), + FunctionDef( + name='fork_module', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Module that contains the fork code')), + Return( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_fork_module', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='str', ctx=Load())), + FunctionDef( + name='_module', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='name', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Imports a module from the fork')), + Return( + value=Call( + func=Attribute( + value=Name(id='importlib', ctx=Load()), + attr='import_module', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='ethereum.'), + FormattedValue( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_fork_module', + ctx=Load()), + conversion=-1), + Constant(value='.'), + FormattedValue( + value=Name(id='name', ctx=Load()), + conversion=-1)])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='proof_of_stake', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Whether the fork is proof of stake')), + For( + target=Name(id='fork', ctx=Store()), + iter=Attribute( + value=Name(id='self', ctx=Load()), + attr='_forks', + ctx=Load()), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='fork', ctx=Load()), + attr='name', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + BinOp( + left=Constant(value='ethereum.'), + op=Add(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='_fork_module', + ctx=Load()))]), + body=[ + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='fork', ctx=Load()), + attr='consensus', + ctx=Load()), + attr='is_pos', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + orelse=[]), + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='fork '), + FormattedValue( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_fork_module', + ctx=Load()), + conversion=-1), + Constant(value=' not discovered')])], + keywords=[]))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_after_fork', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='target_fork_name', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Check if the fork is after the target fork')), + Assign( + targets=[ + Name(id='return_value', ctx=Store())], + value=Constant(value=False)), + For( + target=Name(id='fork', ctx=Store()), + iter=Attribute( + value=Name(id='self', ctx=Load()), + attr='_forks', + ctx=Load()), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='fork', ctx=Load()), + attr='name', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='target_fork_name', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='return_value', ctx=Store())], + value=Constant(value=True))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='fork', ctx=Load()), + attr='name', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + BinOp( + left=Constant(value='ethereum.'), + op=Add(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='_fork_module', + ctx=Load()))]), + body=[ + Break()], + orelse=[])], + orelse=[]), + Return( + value=Name(id='return_value', ctx=Load()))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='calculate_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='calculate_block_difficulty function of the given fork.')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='calculate_block_difficulty', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='calculate_base_fee_per_gas', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='calculate_base_fee_per_gas function of the given fork.')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='calculate_base_fee_per_gas', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='logs_bloom', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='logs_bloom function of the given fork.')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='bloom')], + keywords=[]), + attr='logs_bloom', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='BlockChain', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Block chain class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='BlockChain', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='state_transition', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='state_transition function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='state_transition', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='make_receipt function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='make_receipt', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='signing_hash', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='signing_hash function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='signing_hash', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='signing_hash_pre155', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='signing_hash_pre155 function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='signing_hash_pre155', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='signing_hash_155', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='signing_hash_155 function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='signing_hash_155', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='signing_hash_2930', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='signing_hash_2930 function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='signing_hash_2930', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='signing_hash_1559', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='signing_hash_1559 function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='signing_hash_1559', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='signing_hash_4844', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='signing_hash_4844 function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='signing_hash_4844', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='check_transaction function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='check_transaction', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='process_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='process_transaction function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='process_transaction', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='MAX_BLOB_GAS_PER_BLOCK', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='MAX_BLOB_GAS_PER_BLOCK parameter of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='MAX_BLOB_GAS_PER_BLOCK', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='Block', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Block class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='blocks')], + keywords=[]), + attr='Block', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='Bloom', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Bloom class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork_types')], + keywords=[]), + attr='Bloom', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='Header', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Header class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='blocks')], + keywords=[]), + attr='Header', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='Account', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Account class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='fork_types')], + keywords=[]), + attr='Account', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='Transaction', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Transaction class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='transactions')], + keywords=[]), + attr='Transaction', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='LegacyTransaction', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Legacytransaction class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='transactions')], + keywords=[]), + attr='LegacyTransaction', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='AccessListTransaction', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Access List transaction class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='transactions')], + keywords=[]), + attr='AccessListTransaction', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='FeeMarketTransaction', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Fee Market transaction class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='transactions')], + keywords=[]), + attr='FeeMarketTransaction', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='BlobTransaction', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Blob transaction class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='transactions')], + keywords=[]), + attr='BlobTransaction', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='Withdrawal', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Withdrawal class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='blocks')], + keywords=[]), + attr='Withdrawal', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='encode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='encode_transaction function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='transactions')], + keywords=[]), + attr='encode_transaction', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='decode_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='decode_transaction function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='transactions')], + keywords=[]), + attr='decode_transaction', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='State', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='State class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='State', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='TransientStorage', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Transient storage class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='TransientStorage', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='get_account', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='get_account function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='get_account', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='set_account', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='set_account function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='set_account', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='create_ether', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='create_ether function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='create_ether', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='set_storage', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='set_storage function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='set_storage', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='account_exists_and_is_empty', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='account_exists_and_is_empty function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='account_exists_and_is_empty', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='destroy_touched_empty_accounts', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='destroy_account function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='destroy_touched_empty_accounts', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='destroy_account', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='destroy_account function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='destroy_account', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='process_withdrawal', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='process_withdrawal function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='process_withdrawal', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='state_root', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='state_root function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='state_root', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='close_state', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='close_state function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='close_state', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='Trie', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Trie class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='trie')], + keywords=[]), + attr='Trie', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='root', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Root function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='trie')], + keywords=[]), + attr='root', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='copy_trie', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='copy_trie function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='trie')], + keywords=[]), + attr='copy_trie', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='trie_set function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='trie')], + keywords=[]), + attr='trie_set', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='hex_to_address', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='hex_to_address function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='utils.hexadecimal')], + keywords=[]), + attr='hex_to_address', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='hex_to_root', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='hex_to_root function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='utils.hexadecimal')], + keywords=[]), + attr='hex_to_root', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='Environment', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Environment class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='vm')], + keywords=[]), + attr='Environment', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='Message', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Message class of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='vm')], + keywords=[]), + attr='Message', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='TARGET_BLOB_GAS_PER_BLOCK', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='TARGET_BLOB_GAS_PER_BLOCK of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='vm.gas')], + keywords=[]), + attr='TARGET_BLOB_GAS_PER_BLOCK', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='calculate_total_blob_gas', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='calculate_total_blob_gas function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='vm.gas')], + keywords=[]), + attr='calculate_total_blob_gas', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='process_message_call', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='process_message_call function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='vm.interpreter')], + keywords=[]), + attr='process_message_call', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='apply_dao', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='apply_dao function of the fork')), + Return( + value=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_module', + ctx=Load()), + args=[ + Constant(value='dao')], + keywords=[]), + attr='apply_dao', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load()))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/loaders/fork_loader.v b/coq/ethereum_spec_tools/evm_tools/loaders/fork_loader.v new file mode 100644 index 0000000000..29a15ea91b --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/loaders/fork_loader.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Loader for code from the relevant fork. +*) + diff --git a/coq/ethereum_spec_tools/evm_tools/loaders/transaction_loader.ast b/coq/ethereum_spec_tools/evm_tools/loaders/transaction_loader.ast new file mode 100644 index 0000000000..8b55cb452c --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/loaders/transaction_loader.ast @@ -0,0 +1,1113 @@ +Module( + body=[ + Expr( + value=Constant(value='\nRead transaction data from json file and return the\nrelevant transaction.\n')), + ImportFrom( + module='dataclasses', + names=[ + alias(name='fields')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Any'), + alias(name='List')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes'), + alias(name='Bytes0'), + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum', + names=[ + alias(name='rlp')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes'), + alias(name='hex_to_bytes32'), + alias(name='hex_to_hash'), + alias(name='hex_to_u256'), + alias(name='hex_to_uint')], + level=0), + ClassDef( + name='UnsupportedTx', + bases=[ + Name(id='Exception', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='Exception for unsupported transactions')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='encoded_params', + annotation=Name(id='bytes', ctx=Load())), + arg( + arg='error_message', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='error_message', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='encoded_params', + ctx=Store())], + value=Name(id='encoded_params', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='error_message', + ctx=Store())], + value=Name(id='error_message', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='TransactionLoad', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Class for loading transaction data from json file\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='raw', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='fork', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Store())], + value=Name(id='raw', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Store())], + value=Name(id='fork', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='json_to_chain_id', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get chain ID for the transaction.')), + Return( + value=Call( + func=Name(id='U64', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + decorator_list=[], + returns=Name(id='U64', ctx=Load())), + FunctionDef( + name='json_to_nonce', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get the nonce for the transaction.')), + Return( + value=Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='nonce')], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='json_to_gas_price', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get the gas price for the transaction.')), + Return( + value=Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='gasPrice')], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='json_to_gas', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get the gas limit for the transaction.')), + Return( + value=Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='gasLimit')], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='json_to_to', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get to address for the transaction.')), + If( + test=Compare( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='to')], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value='')]), + body=[ + Return( + value=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='hex_to_address', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='to')], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='json_to_value', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get the value of the transaction.')), + Assign( + targets=[ + Name(id='value', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='value')], + keywords=[])), + If( + test=Compare( + left=Name(id='value', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='0x')]), + body=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='json_to_data', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get the data of the transaction.')), + Return( + value=Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='data')], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Bytes', ctx=Load())), + FunctionDef( + name='json_to_access_list', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get the access list of the transaction.')), + Assign( + targets=[ + Name(id='access_list', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='sublist', ctx=Store()), + iter=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + slice=Constant(value='accessList'), + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='access_list', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='hex_to_address', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='sublist', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='address')], + keywords=[])], + keywords=[]), + ListComp( + elt=Call( + func=Name(id='hex_to_bytes32', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='key', ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='sublist', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='storageKeys')], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='access_list', ctx=Load()))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='json_to_max_priority_fee_per_gas', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get the max priority fee per gas of the transaction.')), + Return( + value=Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='maxPriorityFeePerGas')], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='json_to_max_fee_per_gas', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get the max fee per gas of the transaction.')), + Return( + value=Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='maxFeePerGas')], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='json_to_max_fee_per_blob_gas', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the max priority fee per blobgas of the transaction.\n ')), + Return( + value=Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='maxFeePerBlobGas')], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='json_to_blob_versioned_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get the blob versioned hashes of the transaction.')), + Return( + value=ListComp( + elt=Call( + func=Name(id='hex_to_hash', ctx=Load()), + args=[ + Name(id='blob_hash', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='blob_hash', ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='blobVersionedHashes')], + keywords=[]), + ifs=[], + is_async=0)]))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Bytes32', ctx=Load()), + ctx=Load())), + FunctionDef( + name='json_to_v', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get the v value of the transaction.')), + Return( + value=Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + IfExp( + test=Compare( + left=Constant(value='y_parity'), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load())]), + body=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='y_parity')], + keywords=[]), + orelse=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='v')], + keywords=[]))], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='json_to_y_parity', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get the y parity of the transaction.')), + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='json_to_v', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='json_to_r', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get the r value of the transaction')), + Return( + value=Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='r')], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='json_to_s', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Get the s value of the transaction')), + Return( + value=Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='s')], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='get_parameters', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='tx_cls', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Extract all the transaction parameters from the json file\n ')), + Assign( + targets=[ + Name(id='parameters', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='field', ctx=Store()), + iter=Call( + func=Name(id='fields', ctx=Load()), + args=[ + Name(id='tx_cls', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='parameters', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Call( + func=Name(id='getattr', ctx=Load()), + args=[ + Name(id='self', ctx=Load()), + JoinedStr( + values=[ + Constant(value='json_to_'), + FormattedValue( + value=Attribute( + value=Name(id='field', ctx=Load()), + attr='name', + ctx=Load()), + conversion=-1)])], + keywords=[]), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='parameters', ctx=Load()))], + decorator_list=[], + returns=Name(id='List', ctx=Load())), + FunctionDef( + name='get_legacy_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Return the approprtiate class for legacy transactions.')), + If( + test=Call( + func=Name(id='hasattr', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + Constant(value='LegacyTransaction')], + keywords=[]), + body=[ + Return( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='LegacyTransaction', + ctx=Load()))], + orelse=[ + Return( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Transaction', + ctx=Load()))])], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='read', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Convert json transaction data to a transaction object')), + If( + test=Compare( + left=Constant(value='type'), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='tx_type', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='type')], + keywords=[])), + If( + test=Compare( + left=Name(id='tx_type', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='0x3')]), + body=[ + Assign( + targets=[ + Name(id='tx_cls', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='BlobTransaction', + ctx=Load())), + Assign( + targets=[ + Name(id='tx_byte_prefix', ctx=Store())], + value=Constant(value=b'\x03'))], + orelse=[ + If( + test=Compare( + left=Name(id='tx_type', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='0x2')]), + body=[ + Assign( + targets=[ + Name(id='tx_cls', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='FeeMarketTransaction', + ctx=Load())), + Assign( + targets=[ + Name(id='tx_byte_prefix', ctx=Store())], + value=Constant(value=b'\x02'))], + orelse=[ + If( + test=Compare( + left=Name(id='tx_type', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='0x1')]), + body=[ + Assign( + targets=[ + Name(id='tx_cls', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='AccessListTransaction', + ctx=Load())), + Assign( + targets=[ + Name(id='tx_byte_prefix', ctx=Store())], + value=Constant(value=b'\x01'))], + orelse=[ + If( + test=Compare( + left=Name(id='tx_type', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='0x0')]), + body=[ + Assign( + targets=[ + Name(id='tx_cls', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='get_legacy_transaction', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='tx_byte_prefix', ctx=Store())], + value=Constant(value=b''))], + orelse=[ + Raise( + exc=Call( + func=Name(id='ValueError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Unknown transaction type: '), + FormattedValue( + value=Name(id='tx_type', ctx=Load()), + conversion=-1)])], + keywords=[]))])])])])], + orelse=[ + If( + test=Compare( + left=Constant(value='maxFeePerBlobGas'), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='tx_cls', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='BlobTransaction', + ctx=Load())), + Assign( + targets=[ + Name(id='tx_byte_prefix', ctx=Store())], + value=Constant(value=b'\x03'))], + orelse=[ + If( + test=Compare( + left=Constant(value='maxFeePerGas'), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='tx_cls', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='FeeMarketTransaction', + ctx=Load())), + Assign( + targets=[ + Name(id='tx_byte_prefix', ctx=Store())], + value=Constant(value=b'\x02'))], + orelse=[ + If( + test=Compare( + left=Constant(value='accessList'), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='raw', + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='tx_cls', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='AccessListTransaction', + ctx=Load())), + Assign( + targets=[ + Name(id='tx_byte_prefix', ctx=Store())], + value=Constant(value=b'\x01'))], + orelse=[ + Assign( + targets=[ + Name(id='tx_cls', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='get_legacy_transaction', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='tx_byte_prefix', ctx=Store())], + value=Constant(value=b''))])])])]), + Assign( + targets=[ + Name(id='parameters', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='get_parameters', + ctx=Load()), + args=[ + Name(id='tx_cls', ctx=Load())], + keywords=[])), + Try( + body=[ + Return( + value=Call( + func=Name(id='tx_cls', ctx=Load()), + args=[ + Starred( + value=Name(id='parameters', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='Exception', ctx=Load()), + name='e', + body=[ + Raise( + exc=Call( + func=Name(id='UnsupportedTx', ctx=Load()), + args=[ + BinOp( + left=Name(id='tx_byte_prefix', ctx=Load()), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='parameters', ctx=Load())], + keywords=[])), + Call( + func=Name(id='str', ctx=Load()), + args=[ + Name(id='e', ctx=Load())], + keywords=[])], + keywords=[]), + cause=Name(id='e', ctx=Load()))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Any', ctx=Load()))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/loaders/transaction_loader.v b/coq/ethereum_spec_tools/evm_tools/loaders/transaction_loader.v new file mode 100644 index 0000000000..da2c030b8f --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/loaders/transaction_loader.v @@ -0,0 +1,12 @@ +(* Generated *) +(* +Read transaction data from json file and return the +relevant transaction. +*) + +Require dataclasses. +Require typing. +Require ethereum_types.bytes. +Require ethereum_types.numeric. +Require ethereum. +Require ethereum.utils.hexadecimal. diff --git a/coq/ethereum_spec_tools/evm_tools/statetest/__init__.ast b/coq/ethereum_spec_tools/evm_tools/statetest/__init__.ast new file mode 100644 index 0000000000..086ab38817 --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/statetest/__init__.ast @@ -0,0 +1,1515 @@ +Module( + body=[ + Expr( + value=Constant(value='\nExecute state tests.\n')), + Import( + names=[ + alias(name='argparse')]), + Import( + names=[ + alias(name='json')]), + Import( + names=[ + alias(name='logging')]), + Import( + names=[ + alias(name='sys')]), + ImportFrom( + module='copy', + names=[ + alias(name='deepcopy')], + level=0), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='io', + names=[ + alias(name='StringIO')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Any'), + alias(name='Dict'), + alias(name='Iterable'), + alias(name='List'), + alias(name='Optional'), + alias(name='TextIO')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + module='t8n', + names=[ + alias(name='T8N')], + level=2), + ImportFrom( + module='t8n.t8n_types', + names=[ + alias(name='Result')], + level=2), + ImportFrom( + module='utils', + names=[ + alias(name='get_supported_forks')], + level=2), + ClassDef( + name='TestCase', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A test case derived from the inputs common to all forks and a single\n post-state unique to a single fork.\n ')), + AnnAssign( + target=Name(id='path', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='key', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='index', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='fork_name', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='post', ctx=Store()), + annotation=Name(id='Dict', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='pre', ctx=Store()), + annotation=Name(id='Dict', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Dict', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='transaction', ctx=Store()), + annotation=Name(id='Dict', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + FunctionDef( + name='read_test_cases', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='test_file_path', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Given a path to a filled state test in JSON format, return all the\n `TestCase`s it contains.\n ')), + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='open', ctx=Load()), + args=[ + Name(id='test_file_path', ctx=Load())], + keywords=[]), + optional_vars=Name(id='test_file', ctx=Store()))], + body=[ + Assign( + targets=[ + Name(id='tests', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='test_file', ctx=Load())], + keywords=[]))]), + For( + target=Tuple( + elts=[ + Name(id='key', ctx=Store()), + Name(id='test', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='tests', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Subscript( + value=Name(id='test', ctx=Load()), + slice=Constant(value='env'), + ctx=Load())), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='dict', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Call( + func=Name(id='TypeError', ctx=Load()), + args=[ + Constant(value='env not dict')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='pre', ctx=Store())], + value=Subscript( + value=Name(id='test', ctx=Load()), + slice=Constant(value='pre'), + ctx=Load())), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='pre', ctx=Load()), + Name(id='dict', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Call( + func=Name(id='TypeError', ctx=Load()), + args=[ + Constant(value='pre not dict')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='transaction', ctx=Store())], + value=Subscript( + value=Name(id='test', ctx=Load()), + slice=Constant(value='transaction'), + ctx=Load())), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='transaction', ctx=Load()), + Name(id='dict', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Call( + func=Name(id='TypeError', ctx=Load()), + args=[ + Constant(value='transaction not dict')], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='fork_name', ctx=Store()), + Name(id='content', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Subscript( + value=Name(id='test', ctx=Load()), + slice=Constant(value='post'), + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='idx', ctx=Store()), + Name(id='post', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Name(id='content', ctx=Load())], + keywords=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='post', ctx=Load()), + Name(id='dict', ctx=Load())], + keywords=[])), + body=[ + Raise( + exc=Call( + func=Name(id='TypeError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='post["'), + FormattedValue( + value=Name(id='fork_name', ctx=Load()), + conversion=-1), + Constant(value='"] not dict')])], + keywords=[]))], + orelse=[]), + Expr( + value=Yield( + value=Call( + func=Name(id='TestCase', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='path', + value=Name(id='test_file_path', ctx=Load())), + keyword( + arg='key', + value=Name(id='key', ctx=Load())), + keyword( + arg='index', + value=Name(id='idx', ctx=Load())), + keyword( + arg='fork_name', + value=Name(id='fork_name', ctx=Load())), + keyword( + arg='post', + value=Name(id='post', ctx=Load())), + keyword( + arg='env', + value=Name(id='env', ctx=Load())), + keyword( + arg='pre', + value=Name(id='pre', ctx=Load())), + keyword( + arg='transaction', + value=Name(id='transaction', ctx=Load()))])))], + orelse=[])], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Subscript( + value=Name(id='Iterable', ctx=Load()), + slice=Name(id='TestCase', ctx=Load()), + ctx=Load())), + FunctionDef( + name='run_test_case', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='test_case', + annotation=Name(id='TestCase', ctx=Load())), + arg( + arg='t8n_extra', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + ctx=Load())), + arg( + arg='output_basedir', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=BinOp( + left=Name(id='str', ctx=Load()), + op=BitOr(), + right=Name(id='TextIO', ctx=Load())), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None), + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Runs a single general state test\n ')), + ImportFrom( + names=[ + alias(name='create_parser')], + level=2), + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Name(id='deepcopy', ctx=Load()), + args=[ + Attribute( + value=Name(id='test_case', ctx=Load()), + attr='env', + ctx=Load())], + keywords=[])), + Try( + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='env', ctx=Load()), + slice=Constant(value='blockHashes'), + ctx=Store())], + value=Dict( + keys=[ + Constant(value='0')], + values=[ + Subscript( + value=Name(id='env', ctx=Load()), + slice=Constant(value='previousHash'), + ctx=Load())]))], + handlers=[ + ExceptHandler( + type=Name(id='KeyError', ctx=Load()), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='env', ctx=Load()), + slice=Constant(value='blockHashes'), + ctx=Store())], + value=Dict(keys=[], values=[]))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Subscript( + value=Name(id='env', ctx=Load()), + slice=Constant(value='withdrawals'), + ctx=Store())], + value=List(elts=[], ctx=Load())), + Assign( + targets=[ + Name(id='alloc', ctx=Store())], + value=Call( + func=Name(id='deepcopy', ctx=Load()), + args=[ + Attribute( + value=Name(id='test_case', ctx=Load()), + attr='pre', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='post', ctx=Store())], + value=Call( + func=Name(id='deepcopy', ctx=Load()), + args=[ + Attribute( + value=Name(id='test_case', ctx=Load()), + attr='post', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='d', ctx=Store())], + value=Subscript( + value=Subscript( + value=Name(id='post', ctx=Load()), + slice=Constant(value='indexes'), + ctx=Load()), + slice=Constant(value='data'), + ctx=Load())), + Assign( + targets=[ + Name(id='g', ctx=Store())], + value=Subscript( + value=Subscript( + value=Name(id='post', ctx=Load()), + slice=Constant(value='indexes'), + ctx=Load()), + slice=Constant(value='gas'), + ctx=Load())), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Subscript( + value=Subscript( + value=Name(id='post', ctx=Load()), + slice=Constant(value='indexes'), + ctx=Load()), + slice=Constant(value='value'), + ctx=Load())), + Assign( + targets=[ + Name(id='tx', ctx=Store())], + value=Dict(keys=[], values=[])), + For( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='test_case', ctx=Load()), + attr='transaction', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Compare( + left=Name(id='k', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='data')]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value='input'), + ctx=Store())], + value=Subscript( + value=Name(id='value', ctx=Load()), + slice=Name(id='d', ctx=Load()), + ctx=Load()))], + orelse=[ + If( + test=Compare( + left=Name(id='k', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='gasLimit')]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value='gas'), + ctx=Store())], + value=Subscript( + value=Name(id='value', ctx=Load()), + slice=Name(id='g', ctx=Load()), + ctx=Load()))], + orelse=[ + If( + test=Compare( + left=Name(id='k', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='value')]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Store())], + value=Subscript( + value=Name(id='value', ctx=Load()), + slice=Name(id='v', ctx=Load()), + ctx=Load()))], + orelse=[ + If( + test=Compare( + left=Name(id='k', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='accessLists')]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='value', ctx=Load()), + slice=Name(id='d', ctx=Load()), + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Constant(value='accessList'), + ctx=Store())], + value=Subscript( + value=Name(id='value', ctx=Load()), + slice=Name(id='d', ctx=Load()), + ctx=Load()))], + orelse=[])], + orelse=[ + Assign( + targets=[ + Subscript( + value=Name(id='tx', ctx=Load()), + slice=Name(id='k', ctx=Load()), + ctx=Store())], + value=Name(id='value', ctx=Load()))])])])])], + orelse=[]), + Assign( + targets=[ + Name(id='txs', ctx=Store())], + value=List( + elts=[ + Name(id='tx', ctx=Load())], + ctx=Load())), + Assign( + targets=[ + Name(id='in_stream', ctx=Store())], + value=Call( + func=Name(id='StringIO', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dumps', + ctx=Load()), + args=[ + Dict( + keys=[ + Constant(value='env'), + Constant(value='alloc'), + Constant(value='txs')], + values=[ + Name(id='env', ctx=Load()), + Name(id='alloc', ctx=Load()), + Name(id='txs', ctx=Load())])], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='out_stream', ctx=Store())], + value=Call( + func=Name(id='StringIO', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='t8n_args', ctx=Store())], + value=List( + elts=[ + Constant(value='t8n'), + Constant(value='--input.alloc'), + Constant(value='stdin'), + Constant(value='--input.env'), + Constant(value='stdin'), + Constant(value='--input.txs'), + Constant(value='stdin'), + Constant(value='--state.fork'), + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Name(id='test_case', ctx=Load()), + attr='fork_name', + ctx=Load()), + conversion=-1)])], + ctx=Load())), + If( + test=Compare( + left=Name(id='t8n_extra', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_args', ctx=Load()), + attr='extend', + ctx=Load()), + args=[ + Name(id='t8n_extra', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='parser', ctx=Store())], + value=Call( + func=Name(id='create_parser', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='t8n_options', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='parse_args', + ctx=Load()), + args=[ + Name(id='t8n_args', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='output_basedir', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='t8n_options', ctx=Load()), + attr='output_basedir', + ctx=Store())], + value=Name(id='output_basedir', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='t8n', ctx=Store())], + value=Call( + func=Name(id='T8N', ctx=Load()), + args=[ + Name(id='t8n_options', ctx=Load()), + Name(id='out_stream', ctx=Load()), + Name(id='in_stream', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='apply_body', + ctx=Load()), + args=[], + keywords=[])), + Return( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='result', + ctx=Load()))], + decorator_list=[], + returns=Name(id='Result', ctx=Load())), + FunctionDef( + name='state_test_arguments', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='subparsers', + annotation=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='_SubParsersAction', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the arguments for the statetest tool subparser.\n ')), + Assign( + targets=[ + Name(id='statetest_parser', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='subparsers', ctx=Load()), + attr='add_parser', + ctx=Load()), + args=[ + Constant(value='statetest')], + keywords=[ + keyword( + arg='help', + value=Constant(value='Runs state tests from a file or from the standard input.'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='statetest_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='file')], + keywords=[ + keyword( + arg='nargs', + value=Constant(value='?')), + keyword( + arg='default', + value=Constant(value=None))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='statetest_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--json')], + keywords=[ + keyword( + arg='action', + value=Constant(value='store_true')), + keyword( + arg='default', + value=Constant(value=False))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='statetest_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--noreturndata')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='return_data')), + keyword( + arg='action', + value=Constant(value='store_false')), + keyword( + arg='default', + value=Constant(value=True))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='statetest_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--nostack')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='stack')), + keyword( + arg='action', + value=Constant(value='store_false')), + keyword( + arg='default', + value=Constant(value=True))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='statetest_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--nomemory')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='memory')), + keyword( + arg='action', + value=Constant(value='store_false')), + keyword( + arg='default', + value=Constant(value=True))]))], + decorator_list=[], + returns=Constant(value=None)), + ClassDef( + name='_PrefixFormatter', + bases=[ + Attribute( + value=Name(id='logging', ctx=Load()), + attr='Formatter', + ctx=Load())], + keywords=[], + body=[ + FunctionDef( + name='format', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='record', + annotation=Attribute( + value=Name(id='logging', ctx=Load()), + attr='LogRecord', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='output', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='format', + ctx=Load()), + args=[ + Name(id='record', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Attribute( + value=Constant(value='\n'), + attr='join', + ctx=Load()), + args=[ + GeneratorExp( + elt=BinOp( + left=Constant(value='# '), + op=Add(), + right=Name(id='x', ctx=Load())), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='output', ctx=Load()), + attr='splitlines', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + keywords=[]))], + decorator_list=[], + returns=Name(id='str', ctx=Load()))], + decorator_list=[]), + ClassDef( + name='StateTest', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Run one or more state tests.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='options', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='out_file', + annotation=Name(id='TextIO', ctx=Load())), + arg( + arg='in_file', + annotation=Name(id='TextIO', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='file', + ctx=Store())], + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='file', + ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='out_file', + ctx=Store())], + value=Name(id='out_file', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='in_file', + ctx=Store())], + value=Name(id='in_file', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='supported_forks', + ctx=Store())], + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + GeneratorExp( + elt=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='casefold', + ctx=Load()), + args=[], + keywords=[]), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Call( + func=Name(id='get_supported_forks', ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + keywords=[])), + AnnAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='trace', + ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='json', + ctx=Load()), + simple=0), + AnnAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='memory', + ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='memory', + ctx=Load()), + simple=0), + AnnAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='stack', + ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='stack', + ctx=Load()), + simple=0), + AnnAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='return_data', + ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='return_data', + ctx=Load()), + simple=0)], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='run', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Execute the tests.\n ')), + Assign( + targets=[ + Name(id='logger', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='logging', ctx=Load()), + attr='getLogger', + ctx=Load()), + args=[ + Constant(value='T8N')], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='logger', ctx=Load()), + attr='setLevel', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='level', + value=Attribute( + value=Name(id='logging', ctx=Load()), + attr='INFO', + ctx=Load()))])), + Assign( + targets=[ + Name(id='stream_handler', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='logging', ctx=Load()), + attr='StreamHandler', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='formatter', ctx=Store())], + value=Call( + func=Name(id='_PrefixFormatter', ctx=Load()), + args=[ + Constant(value='%(levelname)s:%(name)s:%(message)s')], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stream_handler', ctx=Load()), + attr='setFormatter', + ctx=Load()), + args=[ + Name(id='formatter', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='logger', ctx=Load()), + attr='addHandler', + ctx=Load()), + args=[ + Name(id='stream_handler', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='file', + ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='run_many', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='run_one', + ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='file', + ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='run_one', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='path', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Execute state tests from a single file.\n ')), + Assign( + targets=[ + Name(id='results', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='test_case', ctx=Store()), + iter=Call( + func=Name(id='read_test_cases', ctx=Load()), + args=[ + Name(id='path', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='test_case', ctx=Load()), + attr='fork_name', + ctx=Load()), + attr='casefold', + ctx=Load()), + args=[], + keywords=[]), + ops=[ + NotIn()], + comparators=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='supported_forks', + ctx=Load())]), + body=[ + Continue()], + orelse=[]), + AnnAssign( + target=Name(id='t8n_extra', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + If( + test=Attribute( + value=Name(id='self', ctx=Load()), + attr='trace', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_extra', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Constant(value='--trace')], + keywords=[]))], + orelse=[]), + If( + test=Attribute( + value=Name(id='self', ctx=Load()), + attr='memory', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_extra', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Constant(value='--trace.memory')], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_extra', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Constant(value='--trace.nomemory')], + keywords=[]))]), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='self', ctx=Load()), + attr='stack', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_extra', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Constant(value='--trace.nostack')], + keywords=[]))], + orelse=[]), + If( + test=Attribute( + value=Name(id='self', ctx=Load()), + attr='return_data', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_extra', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Constant(value='--trace.returndata')], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_extra', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Constant(value='--trace.noreturndata')], + keywords=[]))]), + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Name(id='run_test_case', ctx=Load()), + args=[ + Name(id='test_case', ctx=Load())], + keywords=[ + keyword( + arg='t8n_extra', + value=Name(id='t8n_extra', ctx=Load())), + keyword( + arg='output_basedir', + value=Attribute( + value=Name(id='sys', ctx=Load()), + attr='stderr', + ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dump', + ctx=Load()), + args=[ + Dict( + keys=[ + Constant(value='stateRoot')], + values=[ + BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='result', ctx=Load()), + attr='state_root', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[]))]), + Attribute( + value=Name(id='sys', ctx=Load()), + attr='stderr', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='sys', ctx=Load()), + attr='stderr', + ctx=Load()), + attr='write', + ctx=Load()), + args=[ + Constant(value='\n')], + keywords=[])), + Assign( + targets=[ + Name(id='passed', ctx=Store())], + value=Compare( + left=Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='test_case', ctx=Load()), + attr='post', + ctx=Load()), + slice=Constant(value='hash'), + ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='result', ctx=Load()), + attr='state_root', + ctx=Load())])), + Assign( + targets=[ + Name(id='result_dict', ctx=Store())], + value=Dict( + keys=[ + Constant(value='stateRoot'), + Constant(value='fork'), + Constant(value='name'), + Constant(value='pass')], + values=[ + BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='result', ctx=Load()), + attr='state_root', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[])), + Attribute( + value=Name(id='test_case', ctx=Load()), + attr='fork_name', + ctx=Load()), + Attribute( + value=Name(id='test_case', ctx=Load()), + attr='key', + ctx=Load()), + Name(id='passed', ctx=Load())])), + If( + test=UnaryOp( + op=Not(), + operand=Name(id='passed', ctx=Load())), + body=[ + Assign( + targets=[ + Name(id='actual', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='result', ctx=Load()), + attr='state_root', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='expected', ctx=Store())], + value=Subscript( + value=Subscript( + value=Attribute( + value=Name(id='test_case', ctx=Load()), + attr='post', + ctx=Load()), + slice=Constant(value='hash'), + ctx=Load()), + slice=Slice( + lower=Constant(value=2)), + ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='result_dict', ctx=Load()), + slice=Constant(value='error'), + ctx=Store())], + value=JoinedStr( + values=[ + Constant(value='post state root mismatch: got '), + FormattedValue( + value=Name(id='actual', ctx=Load()), + conversion=-1), + Constant(value=', want '), + FormattedValue( + value=Name(id='expected', ctx=Load()), + conversion=-1)]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='results', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='result_dict', ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dump', + ctx=Load()), + args=[ + Name(id='results', ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='out_file', + ctx=Load())], + keywords=[ + keyword( + arg='indent', + value=Constant(value=4))])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='out_file', + ctx=Load()), + attr='write', + ctx=Load()), + args=[ + Constant(value='\n')], + keywords=[])), + Return( + value=Constant(value=0))], + decorator_list=[], + returns=Name(id='int', ctx=Load())), + FunctionDef( + name='run_many', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Execute state tests from a line-delimited list of files provided from\n `self.in_file`.\n ')), + For( + target=Name(id='line', ctx=Store()), + iter=Attribute( + value=Name(id='self', ctx=Load()), + attr='in_file', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='result', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='run_one', + ctx=Load()), + args=[ + Subscript( + value=Name(id='line', ctx=Load()), + slice=Slice( + upper=UnaryOp( + op=USub(), + operand=Constant(value=1))), + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='result', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=Name(id='result', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Constant(value=0))], + decorator_list=[], + returns=Name(id='int', ctx=Load()))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/statetest/__init__.v b/coq/ethereum_spec_tools/evm_tools/statetest/__init__.v new file mode 100644 index 0000000000..f7bf3eaa5f --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/statetest/__init__.v @@ -0,0 +1,118 @@ +(* Generated *) +(* +Execute state tests. +*) + + +Definition read_test_cases (test_file_path : str) : M (* TODO type *) := + (* + Given a path to a filled state test in JSON format, return all the + `TestCase`s it contains. + *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition run_test_case (test_case : TestCase) (t8n_extra : (* TODO type *)) (output_basedir : (* TODO type *)) : M Result := + (* + Runs a single general state test + *) + (* TODO statement *) + do* M.assign "env" [[ + M.get_local ~(| "deepcopy" |) ~(| + M.get_field ~(| test_case, "env" |) + |) in + ]] in + (* TODO statement *) + (* TODO assignment *) + do* M.assign "alloc" [[ + M.get_local ~(| "deepcopy" |) ~(| + M.get_field ~(| test_case, "pre" |) + |) in + ]] in + do* M.assign "post" [[ + M.get_local ~(| "deepcopy" |) ~(| + M.get_field ~(| test_case, "post" |) + |) in + ]] in + do* M.assign "d" [[ + (* TODO expression *) in + ]] in + do* M.assign "g" [[ + (* TODO expression *) in + ]] in + do* M.assign "v" [[ + (* TODO expression *) in + ]] in + do* M.assign "tx" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "txs" [[ + (* TODO expression *) in + ]] in + do* M.assign "in_stream" [[ + M.get_local ~(| "StringIO" |) ~(| + M.get_field ~(| M.get_local ~(| "json" |), "dumps" |) ~(| + (* TODO expression *) + |) + |) in + ]] in + do* M.assign "out_stream" [[ + M.get_local ~(| "StringIO" |) ~(| + + |) in + ]] in + do* M.assign "t8n_args" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "parser" [[ + M.get_local ~(| "create_parser" |) ~(| + + |) in + ]] in + do* M.assign "t8n_options" [[ + M.get_field ~(| M.get_local ~(| "parser" |), "parse_args" |) ~(| + M.get_local ~(| "t8n_args" |) + |) in + ]] in + (* TODO statement *) + do* M.assign "t8n" [[ + M.get_local ~(| "T8N" |) ~(| + M.get_local ~(| "t8n_options" |), + M.get_local ~(| "out_stream" |), + M.get_local ~(| "in_stream" |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n" |), "apply_body" |) ~(| + + |) ]] in + (* TODO statement *) + M.pure tt. + +Definition state_test_arguments (subparsers : (* TODO type *)) : M unit := + (* + Adds the arguments for the statetest tool subparser. + *) + do* M.assign "statetest_parser" [[ + M.get_field ~(| subparsers, "add_parser" |) ~(| + (* TODO constant *) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "statetest_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "statetest_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "statetest_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "statetest_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "statetest_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + M.pure tt. diff --git a/coq/ethereum_spec_tools/evm_tools/t8n/__init__.ast b/coq/ethereum_spec_tools/evm_tools/t8n/__init__.ast new file mode 100644 index 0000000000..dc74d6a8a8 --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/t8n/__init__.ast @@ -0,0 +1,3374 @@ +Module( + body=[ + Expr( + value=Constant(value='\nCreate a transition tool for the given fork.\n')), + Import( + names=[ + alias(name='argparse')]), + Import( + names=[ + alias(name='json')]), + Import( + names=[ + alias(name='os')]), + ImportFrom( + module='functools', + names=[ + alias(name='partial')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Any'), + alias(name='TextIO')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum', + names=[ + alias(name='rlp'), + alias(name='trace')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.exceptions', + names=[ + alias(name='EthereumException'), + alias(name='InvalidBlock')], + level=0), + ImportFrom( + module='ethereum_spec_tools.forks', + names=[ + alias(name='Hardfork')], + level=0), + ImportFrom( + module='loaders.fixture_loader', + names=[ + alias(name='Load')], + level=2), + ImportFrom( + module='loaders.fork_loader', + names=[ + alias(name='ForkLoad')], + level=2), + ImportFrom( + module='utils', + names=[ + alias(name='FatalException'), + alias(name='get_module_name'), + alias(name='get_stream_logger'), + alias(name='parse_hex_or_int')], + level=2), + ImportFrom( + module='env', + names=[ + alias(name='Env')], + level=1), + ImportFrom( + module='evm_trace', + names=[ + alias(name='evm_trace'), + alias(name='output_traces')], + level=1), + ImportFrom( + module='t8n_types', + names=[ + alias(name='Alloc'), + alias(name='Result'), + alias(name='Txs')], + level=1), + FunctionDef( + name='t8n_arguments', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='subparsers', + annotation=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='_SubParsersAction', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds the arguments for the t8n tool subparser.\n ')), + Assign( + targets=[ + Name(id='t8n_parser', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='subparsers', ctx=Load()), + attr='add_parser', + ctx=Load()), + args=[ + Constant(value='t8n')], + keywords=[ + keyword( + arg='help', + value=Constant(value='This is the t8n tool.'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--input.alloc')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='input_alloc')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='default', + value=Constant(value='alloc.json'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--input.env')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='input_env')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='default', + value=Constant(value='env.json'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--input.txs')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='input_txs')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='default', + value=Constant(value='txs.json'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--output.alloc')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='output_alloc')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='default', + value=Constant(value='alloc.json'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--output.basedir')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='output_basedir')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='default', + value=Constant(value='.'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--output.body')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='output_body')), + keyword( + arg='type', + value=Name(id='str', ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--output.result')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='output_result')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='default', + value=Constant(value='result.json'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--state.chainid')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='state_chainid')), + keyword( + arg='type', + value=Name(id='int', ctx=Load())), + keyword( + arg='default', + value=Constant(value=1))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--state.fork')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='state_fork')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='default', + value=Constant(value='Frontier'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--state.reward')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='state_reward')), + keyword( + arg='type', + value=Name(id='int', ctx=Load())), + keyword( + arg='default', + value=Constant(value=0))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--trace')], + keywords=[ + keyword( + arg='action', + value=Constant(value='store_true'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--trace.memory')], + keywords=[ + keyword( + arg='action', + value=Constant(value='store_true'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--trace.nomemory')], + keywords=[ + keyword( + arg='action', + value=Constant(value='store_true'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--trace.noreturndata')], + keywords=[ + keyword( + arg='action', + value=Constant(value='store_true'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--trace.nostack')], + keywords=[ + keyword( + arg='action', + value=Constant(value='store_true'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='t8n_parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--trace.returndata')], + keywords=[ + keyword( + arg='action', + value=Constant(value='store_true'))]))], + decorator_list=[], + returns=Constant(value=None)), + ClassDef( + name='T8N', + bases=[ + Name(id='Load', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='The class that carries out the transition')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='options', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='out_file', + annotation=Name(id='TextIO', ctx=Load())), + arg( + arg='in_file', + annotation=Name(id='TextIO', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='out_file', + ctx=Store())], + value=Name(id='out_file', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='in_file', + ctx=Store())], + value=Name(id='in_file', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Store())], + value=Name(id='options', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='forks', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Hardfork', ctx=Load()), + attr='discover', + ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=Constant(value='stdin'), + ops=[ + In()], + comparators=[ + Tuple( + elts=[ + Attribute( + value=Name(id='options', ctx=Load()), + attr='input_env', + ctx=Load()), + Attribute( + value=Name(id='options', ctx=Load()), + attr='input_alloc', + ctx=Load()), + Attribute( + value=Name(id='options', ctx=Load()), + attr='input_txs', + ctx=Load())], + ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='stdin', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='in_file', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='stdin', ctx=Store())], + value=Constant(value=None))]), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='fork_module', ctx=Store()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='fork_block', + ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='get_module_name', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='forks', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + Name(id='stdin', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Store())], + value=Call( + func=Name(id='ForkLoad', ctx=Load()), + args=[ + Name(id='fork_module', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='trace', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='trace_memory', ctx=Store())], + value=Call( + func=Name(id='getattr', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + Constant(value='trace.memory'), + Constant(value=False)], + keywords=[])), + Assign( + targets=[ + Name(id='trace_stack', ctx=Store())], + value=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='getattr', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + Constant(value='trace.nostack'), + Constant(value=False)], + keywords=[]))), + Assign( + targets=[ + Name(id='trace_return_data', ctx=Store())], + value=Call( + func=Name(id='getattr', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + Constant(value='trace.returndata')], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='trace', ctx=Load()), + attr='evm_trace', + ctx=Store())], + value=Call( + func=Name(id='partial', ctx=Load()), + args=[ + Name(id='evm_trace', ctx=Load())], + keywords=[ + keyword( + arg='trace_memory', + value=Name(id='trace_memory', ctx=Load())), + keyword( + arg='trace_stack', + value=Name(id='trace_stack', ctx=Load())), + keyword( + arg='trace_return_data', + value=Name(id='trace_return_data', ctx=Load()))]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='logger', + ctx=Store())], + value=Call( + func=Name(id='get_stream_logger', ctx=Load()), + args=[ + Constant(value='T8N')], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='state_fork', + ctx=Load()), + Name(id='fork_module', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='chain_id', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='state_chainid', + ctx=Load()), + Name(id='U64', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Store())], + value=Call( + func=Name(id='Alloc', ctx=Load()), + args=[ + Name(id='self', ctx=Load()), + Name(id='stdin', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Store())], + value=Call( + func=Name(id='Env', ctx=Load()), + args=[ + Name(id='self', ctx=Load()), + Name(id='stdin', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='txs', + ctx=Store())], + value=Call( + func=Name(id='Txs', ctx=Load()), + args=[ + Name(id='self', ctx=Load()), + Name(id='stdin', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='result', + ctx=Store())], + value=Call( + func=Name(id='Result', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_difficulty', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.cancun')], + keywords=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='SYSTEM_ADDRESS', + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='hex_to_address', + ctx=Load()), + args=[ + Constant(value='0xfffffffffffffffffffffffffffffffffffffffe')], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='BEACON_ROOTS_ADDRESS', + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='hex_to_address', + ctx=Load()), + args=[ + Constant(value='0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02')], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='SYSTEM_TRANSACTION_GAS', + ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=30000000)], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='BLOCK_REWARD', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n For the t8n tool, the block reward is\n provided as a command line option\n ')), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='state_reward', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Constant(value=0)]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.paris')], + keywords=[])]), + body=[ + Return( + value=Constant(value=None))], + orelse=[ + Return( + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='state_reward', + ctx=Load())], + keywords=[]))])], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='check_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='tx', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Implements the check_transaction function of the fork.\n The arguments to be passed are adjusted according to the fork.\n ')), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.cancun')], + keywords=[]), + body=[ + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='check_transaction', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='tx', ctx=Load()), + Name(id='gas_available', ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='chain_id', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='excess_blob_gas', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='arguments', ctx=Store())], + value=List( + elts=[ + Name(id='tx', ctx=Load())], + ctx=Load())), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.london')], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='arguments', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='arguments', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='gas_available', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.spurious_dragon')], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='arguments', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='check_transaction', + ctx=Load()), + args=[ + Starred( + value=Name(id='arguments', ctx=Load()), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='environment', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='tx', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create the environment for the transaction. The keyword\n arguments are adjusted according to the fork.\n ')), + Assign( + targets=[ + Name(id='kw_arguments', ctx=Store())], + value=Dict( + keys=[ + Constant(value='block_hashes'), + Constant(value='coinbase'), + Constant(value='number'), + Constant(value='gas_limit'), + Constant(value='time'), + Constant(value='state')], + values=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_number', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_gas_limit', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_timestamp', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state', + ctx=Load())])), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.paris')], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='prev_randao'), + ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='prev_randao', + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='difficulty'), + ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_difficulty', + ctx=Load()))]), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.istanbul')], + keywords=[]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='chain_id'), + ctx=Store())], + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='chain_id', + ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='check_tx_return', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='check_transaction', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='gas_available', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.cancun')], + keywords=[]), + body=[ + Assign( + targets=[ + Tuple( + elts=[ + Name(id='sender_address', ctx=Store()), + Name(id='effective_gas_price', ctx=Store()), + Name(id='blob_versioned_hashes', ctx=Store())], + ctx=Store())], + value=Name(id='check_tx_return', ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='base_fee_per_gas'), + ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='caller'), + ctx=Store()), + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='origin'), + ctx=Store())], + value=Name(id='sender_address', ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='gas_price'), + ctx=Store())], + value=Name(id='effective_gas_price', ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='blob_versioned_hashes'), + ctx=Store())], + value=Name(id='blob_versioned_hashes', ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='excess_blob_gas'), + ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='excess_blob_gas', + ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='transient_storage'), + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='TransientStorage', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.london')], + keywords=[]), + body=[ + Assign( + targets=[ + Tuple( + elts=[ + Name(id='sender_address', ctx=Store()), + Name(id='effective_gas_price', ctx=Store())], + ctx=Store())], + value=Name(id='check_tx_return', ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='base_fee_per_gas'), + ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='caller'), + ctx=Store()), + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='origin'), + ctx=Store())], + value=Name(id='sender_address', ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='gas_price'), + ctx=Store())], + value=Name(id='effective_gas_price', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='sender_address', ctx=Store())], + value=Name(id='check_tx_return', ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='caller'), + ctx=Store()), + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='origin'), + ctx=Store())], + value=Name(id='sender_address', ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='gas_price'), + ctx=Store())], + value=Attribute( + value=Name(id='tx', ctx=Load()), + attr='gas_price', + ctx=Load()))])]), + Assign( + targets=[ + Subscript( + value=Name(id='kw_arguments', ctx=Load()), + slice=Constant(value='traces'), + ctx=Store())], + value=List(elts=[], ctx=Load())), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + value=Name(id='kw_arguments', ctx=Load()))]))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='tx_trie_set', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='trie', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='index', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='tx', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Add a transaction to the trie.')), + Assign( + targets=[ + Name(id='arguments', ctx=Store())], + value=List( + elts=[ + Name(id='trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='index', ctx=Load())], + keywords=[])], + keywords=[])], + ctx=Load())), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.berlin')], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='arguments', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='encode_transaction', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='arguments', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='trie_set', + ctx=Load()), + args=[ + Starred( + value=Name(id='arguments', ctx=Load()), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='make_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='tx', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='process_transaction_return', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='gas_available', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Create a transaction receipt.')), + Assign( + targets=[ + Name(id='arguments', ctx=Store())], + value=List( + elts=[ + Name(id='tx', ctx=Load())], + ctx=Load())), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.byzantium')], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='arguments', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Subscript( + value=Name(id='process_transaction_return', ctx=Load()), + slice=Constant(value=2), + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='arguments', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='state_root', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])], + keywords=[]))]), + Expr( + value=Call( + func=Attribute( + value=Name(id='arguments', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_gas_limit', + ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='arguments', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Subscript( + value=Name(id='process_transaction_return', ctx=Load()), + slice=Constant(value=1), + ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='make_receipt', + ctx=Load()), + args=[ + Starred( + value=Name(id='arguments', ctx=Load()), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='pay_rewards', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pay the miner and the ommers.\n This function is re-implemented since the uncle header\n might not be available in the t8n tool.\n ')), + Assign( + targets=[ + Name(id='coinbase', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())), + Assign( + targets=[ + Name(id='ommers', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='ommers', + ctx=Load())), + Assign( + targets=[ + Name(id='state', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state', + ctx=Load())), + Assign( + targets=[ + Name(id='miner_reward', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='BLOCK_REWARD', + ctx=Load()), + op=Add(), + right=BinOp( + left=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='ommers', ctx=Load())], + keywords=[])], + keywords=[]), + op=Mult(), + right=BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='BLOCK_REWARD', + ctx=Load()), + op=FloorDiv(), + right=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=32)], + keywords=[]))))), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='create_ether', + ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='coinbase', ctx=Load()), + Name(id='miner_reward', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='touched_accounts', ctx=Store())], + value=List( + elts=[ + Name(id='coinbase', ctx=Load())], + ctx=Load())), + For( + target=Name(id='ommer', ctx=Store()), + iter=Name(id='ommers', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='ommer_miner_reward', ctx=Store())], + value=BinOp( + left=BinOp( + left=BinOp( + left=Constant(value=8), + op=Sub(), + right=Attribute( + value=Name(id='ommer', ctx=Load()), + attr='delta', + ctx=Load())), + op=Mult(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='BLOCK_REWARD', + ctx=Load())), + op=FloorDiv(), + right=Constant(value=8))), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='create_ether', + ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='address', + ctx=Load()), + Name(id='ommer_miner_reward', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='touched_accounts', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Attribute( + value=Name(id='ommer', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.spurious_dragon')], + keywords=[]), + body=[ + For( + target=Name(id='account', ctx=Store()), + iter=Name(id='touched_accounts', ctx=Load()), + body=[ + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='account_exists_and_is_empty', + ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='destroy_account', + ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Name(id='account', ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='backup_state', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Back up the state in order to restore in case of an error.')), + Assign( + targets=[ + Name(id='state', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state', + ctx=Load())), + Assign( + targets=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state_backup', + ctx=Store())], + value=Tuple( + elts=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='copy_trie', + ctx=Load()), + args=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Load())], + keywords=[]), + DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='copy_trie', + ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='t', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='restore_state', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Restore the state from the backup.')), + Assign( + targets=[ + Name(id='state', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state', + ctx=Load())), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='state', ctx=Load()), + attr='_main_trie', + ctx=Store()), + Attribute( + value=Name(id='state', ctx=Load()), + attr='_storage_tries', + ctx=Store())], + ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state_backup', + ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='apply_body', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n The apply body function is seen as the entry point of\n the t8n tool into the designated fork. The function has been\n re-implemented here to account for the differences in the\n transaction processing between the forks. However, the general\n structure of the function is the same.\n ')), + Assign( + targets=[ + Name(id='block_gas_limit', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_gas_limit', + ctx=Load())), + Assign( + targets=[ + Name(id='gas_available', ctx=Store())], + value=Name(id='block_gas_limit', ctx=Load())), + Assign( + targets=[ + Name(id='transactions_trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Trie', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))])), + Assign( + targets=[ + Name(id='receipts_trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Trie', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))])), + Assign( + targets=[ + Name(id='block_logs', ctx=Store())], + value=Tuple(elts=[], ctx=Load())), + Assign( + targets=[ + Name(id='blob_gas_used', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.cancun')], + keywords=[]), + Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='parent_beacon_block_root', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])]), + body=[ + Assign( + targets=[ + Name(id='beacon_block_roots_contract_code', ctx=Store())], + value=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='get_account', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='BEACON_ROOTS_ADDRESS', + ctx=Load())], + keywords=[]), + attr='code', + ctx=Load())), + Assign( + targets=[ + Name(id='system_tx_message', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Message', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='SYSTEM_ADDRESS', + ctx=Load())), + keyword( + arg='target', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='BEACON_ROOTS_ADDRESS', + ctx=Load())), + keyword( + arg='gas', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='SYSTEM_TRANSACTION_GAS', + ctx=Load())), + keyword( + arg='value', + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='data', + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='parent_beacon_block_root', + ctx=Load())), + keyword( + arg='code', + value=Name(id='beacon_block_roots_contract_code', ctx=Load())), + keyword( + arg='depth', + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + keyword( + arg='current_target', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='BEACON_ROOTS_ADDRESS', + ctx=Load())), + keyword( + arg='code_address', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='BEACON_ROOTS_ADDRESS', + ctx=Load())), + keyword( + arg='should_transfer_value', + value=Constant(value=False)), + keyword( + arg='is_static', + value=Constant(value=False)), + keyword( + arg='accessed_addresses', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='accessed_storage_keys', + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + keyword( + arg='parent_evm', + value=Constant(value=None))])), + Assign( + targets=[ + Name(id='system_tx_env', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Environment', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='caller', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='SYSTEM_ADDRESS', + ctx=Load())), + keyword( + arg='origin', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='SYSTEM_ADDRESS', + ctx=Load())), + keyword( + arg='block_hashes', + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_hashes', + ctx=Load())), + keyword( + arg='coinbase', + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='coinbase', + ctx=Load())), + keyword( + arg='number', + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_number', + ctx=Load())), + keyword( + arg='gas_limit', + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_gas_limit', + ctx=Load())), + keyword( + arg='base_fee_per_gas', + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())), + keyword( + arg='gas_price', + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='base_fee_per_gas', + ctx=Load())), + keyword( + arg='time', + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='block_timestamp', + ctx=Load())), + keyword( + arg='prev_randao', + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='prev_randao', + ctx=Load())), + keyword( + arg='state', + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state', + ctx=Load())), + keyword( + arg='chain_id', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='chain_id', + ctx=Load())), + keyword( + arg='traces', + value=List(elts=[], ctx=Load())), + keyword( + arg='excess_blob_gas', + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='excess_blob_gas', + ctx=Load())), + keyword( + arg='blob_versioned_hashes', + value=Tuple(elts=[], ctx=Load())), + keyword( + arg='transient_storage', + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='TransientStorage', + ctx=Load()), + args=[], + keywords=[]))])), + Assign( + targets=[ + Name(id='system_tx_output', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='process_message_call', + ctx=Load()), + args=[ + Name(id='system_tx_message', ctx=Load()), + Name(id='system_tx_env', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='destroy_touched_empty_accounts', + ctx=Load()), + args=[ + Attribute( + value=Name(id='system_tx_env', ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='system_tx_output', ctx=Load()), + attr='touched_accounts', + ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Tuple( + elts=[ + Name(id='tx_idx', ctx=Store()), + Name(id='tx', ctx=Store())], + ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='txs', + ctx=Load()), + attr='transactions', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='backup_state', + ctx=Load()), + args=[], + keywords=[])), + Try( + body=[ + Assign( + targets=[ + Name(id='env', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='environment', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='gas_available', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='process_transaction_return', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='process_transaction', + ctx=Load()), + args=[ + Name(id='env', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.cancun')], + keywords=[]), + body=[ + AugAssign( + target=Name(id='blob_gas_used', ctx=Store()), + op=Add(), + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='calculate_total_blob_gas', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='blob_gas_used', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='MAX_BLOB_GAS_PER_BLOCK', + ctx=Load())]), + body=[ + Raise( + exc=Name(id='InvalidBlock', ctx=Load()))], + orelse=[])], + orelse=[])], + handlers=[ + ExceptHandler( + type=Name(id='EthereumException', ctx=Load()), + name='e', + body=[ + Assign( + targets=[ + Subscript( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='txs', + ctx=Load()), + attr='rejected_txs', + ctx=Load()), + slice=Name(id='tx_idx', ctx=Load()), + ctx=Store())], + value=JoinedStr( + values=[ + Constant(value='Failed transaction: '), + FormattedValue( + value=Name(id='e', ctx=Load()), + conversion=114)])), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='restore_state', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='logger', + ctx=Load()), + attr='warning', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Transaction '), + FormattedValue( + value=Name(id='tx_idx', ctx=Load()), + conversion=-1), + Constant(value=' failed: '), + FormattedValue( + value=Name(id='e', ctx=Load()), + conversion=114)])], + keywords=[]))])], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='txs', + ctx=Load()), + attr='add_transaction', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='gas_consumed', ctx=Store())], + value=Subscript( + value=Name(id='process_transaction_return', ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + AugAssign( + target=Name(id='gas_available', ctx=Store()), + op=Sub(), + value=Name(id='gas_consumed', ctx=Load())), + If( + test=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='trace', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='tx_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='txs', + ctx=Load()), + attr='get_tx_hash', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='output_traces', ctx=Load()), + args=[ + Attribute( + value=Name(id='env', ctx=Load()), + attr='traces', + ctx=Load()), + Name(id='i', ctx=Load()), + Name(id='tx_hash', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='output_basedir', + ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='tx_trie_set', + ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load()), + Name(id='i', ctx=Load()), + Name(id='tx', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='receipt', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='make_receipt', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='process_transaction_return', ctx=Load()), + Name(id='gas_available', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='trie_set', + ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Name(id='receipt', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='txs', + ctx=Load()), + attr='add_receipt', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='gas_consumed', ctx=Load())], + keywords=[])), + AugAssign( + target=Name(id='block_logs', ctx=Store()), + op=Add(), + value=Subscript( + value=Name(id='process_transaction_return', ctx=Load()), + slice=Constant(value=1), + ctx=Load())), + Assign( + targets=[ + Attribute( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state', + ctx=Load()), + attr='_snapshots', + ctx=Store())], + value=List(elts=[], ctx=Load()))], + finalbody=[])], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='BLOCK_REWARD', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='pay_rewards', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='block_gas_used', ctx=Store())], + value=BinOp( + left=Name(id='block_gas_limit', ctx=Load()), + op=Sub(), + right=Name(id='gas_available', ctx=Load()))), + Assign( + targets=[ + Name(id='block_logs_bloom', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='logs_bloom', + ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='logs_hash', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='block_logs', ctx=Load())], + keywords=[])], + keywords=[])), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.shanghai')], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='withdrawals_trie', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Trie', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='secured', + value=Constant(value=False)), + keyword( + arg='default', + value=Constant(value=None))])), + For( + target=Tuple( + elts=[ + Name(id='i', ctx=Store()), + Name(id='wd', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='withdrawals', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='trie_set', + ctx=Load()), + args=[ + Name(id='withdrawals_trie', ctx=Load()), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + keywords=[]), + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='wd', ctx=Load())], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='process_withdrawal', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state', + ctx=Load()), + Name(id='wd', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='account_exists_and_is_empty', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='wd', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='destroy_account', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state', + ctx=Load()), + Attribute( + value=Name(id='wd', ctx=Load()), + attr='address', + ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='result', + ctx=Load()), + attr='withdrawals_root', + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='root', + ctx=Load()), + args=[ + Name(id='withdrawals_trie', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.cancun')], + keywords=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='result', + ctx=Load()), + attr='blob_gas_used', + ctx=Store())], + value=Name(id='blob_gas_used', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='result', + ctx=Load()), + attr='excess_blob_gas', + ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='env', + ctx=Load()), + attr='excess_blob_gas', + ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='result', + ctx=Load()), + attr='state_root', + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='state_root', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='result', + ctx=Load()), + attr='tx_root', + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='root', + ctx=Load()), + args=[ + Name(id='transactions_trie', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='result', + ctx=Load()), + attr='receipt_root', + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='fork', + ctx=Load()), + attr='root', + ctx=Load()), + args=[ + Name(id='receipts_trie', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='result', + ctx=Load()), + attr='bloom', + ctx=Store())], + value=Name(id='block_logs_bloom', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='result', + ctx=Load()), + attr='logs_hash', + ctx=Store())], + value=Name(id='logs_hash', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='result', + ctx=Load()), + attr='rejected', + ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='txs', + ctx=Load()), + attr='rejected_txs', + ctx=Load())), + Assign( + targets=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='result', + ctx=Load()), + attr='receipts', + ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='txs', + ctx=Load()), + attr='successful_receipts', + ctx=Load())), + Assign( + targets=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='result', + ctx=Load()), + attr='gas_used', + ctx=Store())], + value=Name(id='block_gas_used', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='run', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Run the transition and provide the relevant outputs')), + Try( + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='apply_body', + ctx=Load()), + args=[], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='FatalException', ctx=Load()), + name='e', + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='logger', + ctx=Load()), + attr='error', + ctx=Load()), + args=[ + Call( + func=Name(id='str', ctx=Load()), + args=[ + Name(id='e', ctx=Load())], + keywords=[])], + keywords=[])), + Return( + value=Constant(value=1))])], + orelse=[], + finalbody=[]), + Assign( + targets=[ + Name(id='json_state', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='alloc', + ctx=Load()), + attr='to_json', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='json_result', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='result', + ctx=Load()), + attr='to_json', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='json_output', ctx=Store())], + value=Dict(keys=[], values=[])), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='output_body', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='stdout')]), + body=[ + Assign( + targets=[ + Name(id='txs_rlp', ctx=Store())], + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='txs', + ctx=Load()), + attr='all_txs', + ctx=Load())], + keywords=[]), + attr='hex', + ctx=Load()), + args=[], + keywords=[]))), + Assign( + targets=[ + Subscript( + value=Name(id='json_output', ctx=Load()), + slice=Constant(value='body'), + ctx=Store())], + value=Name(id='txs_rlp', ctx=Load()))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='output_body', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='txs_rlp_path', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='os', ctx=Load()), + attr='path', + ctx=Load()), + attr='join', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='output_basedir', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='output_body', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='txs_rlp', ctx=Store())], + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='txs', + ctx=Load()), + attr='all_txs', + ctx=Load())], + keywords=[]), + attr='hex', + ctx=Load()), + args=[], + keywords=[]))), + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='open', ctx=Load()), + args=[ + Name(id='txs_rlp_path', ctx=Load()), + Constant(value='w')], + keywords=[]), + optional_vars=Name(id='f', ctx=Store()))], + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dump', + ctx=Load()), + args=[ + Name(id='txs_rlp', ctx=Load()), + Name(id='f', ctx=Load())], + keywords=[]))]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='logger', + ctx=Load()), + attr='info', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Wrote transaction rlp to '), + FormattedValue( + value=Name(id='txs_rlp_path', ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[])]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='output_alloc', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='stdout')]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='json_output', ctx=Load()), + slice=Constant(value='alloc'), + ctx=Store())], + value=Name(id='json_state', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='alloc_output_path', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='os', ctx=Load()), + attr='path', + ctx=Load()), + attr='join', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='output_basedir', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='output_alloc', + ctx=Load())], + keywords=[])), + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='open', ctx=Load()), + args=[ + Name(id='alloc_output_path', ctx=Load()), + Constant(value='w')], + keywords=[]), + optional_vars=Name(id='f', ctx=Store()))], + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dump', + ctx=Load()), + args=[ + Name(id='json_state', ctx=Load()), + Name(id='f', ctx=Load())], + keywords=[ + keyword( + arg='indent', + value=Constant(value=4))]))]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='logger', + ctx=Load()), + attr='info', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Wrote alloc to '), + FormattedValue( + value=Name(id='alloc_output_path', ctx=Load()), + conversion=-1)])], + keywords=[]))]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='output_result', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='stdout')]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='json_output', ctx=Load()), + slice=Constant(value='result'), + ctx=Store())], + value=Name(id='json_result', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='result_output_path', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='os', ctx=Load()), + attr='path', + ctx=Load()), + attr='join', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='output_basedir', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='output_result', + ctx=Load())], + keywords=[])), + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='open', ctx=Load()), + args=[ + Name(id='result_output_path', ctx=Load()), + Constant(value='w')], + keywords=[]), + optional_vars=Name(id='f', ctx=Store()))], + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dump', + ctx=Load()), + args=[ + Name(id='json_result', ctx=Load()), + Name(id='f', ctx=Load())], + keywords=[ + keyword( + arg='indent', + value=Constant(value=4))]))]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='logger', + ctx=Load()), + attr='info', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Wrote result to '), + FormattedValue( + value=Name(id='result_output_path', ctx=Load()), + conversion=-1)])], + keywords=[]))]), + If( + test=Name(id='json_output', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dump', + ctx=Load()), + args=[ + Name(id='json_output', ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='out_file', + ctx=Load())], + keywords=[ + keyword( + arg='indent', + value=Constant(value=4))]))], + orelse=[]), + Return( + value=Constant(value=0))], + decorator_list=[], + returns=Name(id='int', ctx=Load()))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/t8n/__init__.v b/coq/ethereum_spec_tools/evm_tools/t8n/__init__.v new file mode 100644 index 0000000000..c38cfe6a82 --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/t8n/__init__.v @@ -0,0 +1,64 @@ +(* Generated *) +(* +Create a transition tool for the given fork. +*) + + +Definition t8n_arguments (subparsers : (* TODO type *)) : M unit := + (* + Adds the arguments for the t8n tool subparser. + *) + do* M.assign "t8n_parser" [[ + M.get_field ~(| subparsers, "add_parser" |) ~(| + (* TODO constant *) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "t8n_parser" |), "add_argument" |) ~(| + (* TODO constant *) + |) ]] in + M.pure tt. diff --git a/coq/ethereum_spec_tools/evm_tools/t8n/env.ast b/coq/ethereum_spec_tools/evm_tools/t8n/env.ast new file mode 100644 index 0000000000..66c2f2d875 --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/t8n/env.ast @@ -0,0 +1,1480 @@ +Module( + body=[ + Expr( + value=Constant(value='\nDefine t8n Env class\n')), + Import( + names=[ + alias(name='json')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='TYPE_CHECKING'), + alias(name='Any'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes32')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum', + names=[ + alias(name='rlp')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32'), + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.byte', + names=[ + alias(name='left_pad_zero_bytes')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes')], + level=0), + ImportFrom( + module='utils', + names=[ + alias(name='parse_hex_or_int')], + level=2), + If( + test=Name(id='TYPE_CHECKING', ctx=Load()), + body=[ + ImportFrom( + module='ethereum_spec_tools.evm_tools.t8n', + names=[ + alias(name='T8N')], + level=0)], + orelse=[]), + ClassDef( + name='Ommer', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='The Ommer type for the t8n tool.')), + AnnAssign( + target=Name(id='delta', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='address', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Env', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The environment for the transition tool.\n ')), + AnnAssign( + target=Name(id='coinbase', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_gas_limit', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_timestamp', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='withdrawals', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_difficulty', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='prev_randao', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Bytes32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_difficulty', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_timestamp', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee_per_gas', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_gas_used', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_gas_limit', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_base_fee_per_gas', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Any', ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_ommers_hash', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_beacon_block_root', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Hash32', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_excess_blob_gas', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='U64', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_blob_gas_used', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='U64', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='excess_blob_gas', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='U64', ctx=Load()), + ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='t8n', + annotation=Constant(value='T8N')), + arg( + arg='stdin', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Dict', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='options', + ctx=Load()), + attr='input_env', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='stdin')]), + body=[ + Assert( + test=Compare( + left=Name(id='stdin', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Subscript( + value=Name(id='stdin', ctx=Load()), + slice=Constant(value='env'), + ctx=Load()))], + orelse=[ + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='open', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='options', + ctx=Load()), + attr='input_env', + ctx=Load()), + Constant(value='r')], + keywords=[]), + optional_vars=Name(id='f', ctx=Store()))], + body=[ + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='f', ctx=Load())], + keywords=[]))])]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='coinbase', + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='hex_to_address', + ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='currentCoinbase'), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_gas_limit', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='currentGasLimit'), + ctx=Load()), + Name(id='Uint', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='currentNumber'), + ctx=Load()), + Name(id='Uint', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_timestamp', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='currentTimestamp'), + ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='read_block_difficulty', + ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='t8n', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='read_base_fee_per_gas', + ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='t8n', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='read_randao', + ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='t8n', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='read_block_hashes', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='read_ommers', + ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='t8n', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='read_withdrawals', + ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='t8n', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.cancun')], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='parent_beacon_block_root_hex', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='parentBeaconBlockRoot')], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_beacon_block_root', + ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='parent_beacon_block_root_hex', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=Call( + func=Name(id='Bytes32', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Name(id='parent_beacon_block_root_hex', ctx=Load())], + keywords=[])], + keywords=[]), + orelse=Constant(value=None))), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='read_excess_blob_gas', + ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='t8n', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[]), + FunctionDef( + name='read_excess_blob_gas', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='data', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='t8n', + annotation=Constant(value='T8N'))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read the excess_blob_gas from the data. If the excess blob gas is\n not present, it is calculated from the parent block parameters.\n ')), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_blob_gas_used', + ctx=Store())], + value=Call( + func=Name(id='U64', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_excess_blob_gas', + ctx=Store())], + value=Call( + func=Name(id='U64', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='excess_blob_gas', + ctx=Store())], + value=Constant(value=None)), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.cancun')], + keywords=[])), + body=[ + Return()], + orelse=[]), + If( + test=Compare( + left=Constant(value='currentExcessBlobGas'), + ops=[ + In()], + comparators=[ + Name(id='data', ctx=Load())]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='excess_blob_gas', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='currentExcessBlobGas'), + ctx=Load()), + Name(id='U64', ctx=Load())], + keywords=[])), + Return()], + orelse=[]), + If( + test=Compare( + left=Constant(value='parentExcessBlobGas'), + ops=[ + In()], + comparators=[ + Name(id='data', ctx=Load())]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_excess_blob_gas', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='parentExcessBlobGas'), + ctx=Load()), + Name(id='U64', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Constant(value='parentBlobGasUsed'), + ops=[ + In()], + comparators=[ + Name(id='data', ctx=Load())]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_blob_gas_used', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='parentBlobGasUsed'), + ctx=Load()), + Name(id='U64', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='excess_blob_gas', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_excess_blob_gas', + ctx=Load()), + op=Add(), + right=Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_blob_gas_used', + ctx=Load()))), + Assign( + targets=[ + Name(id='target_blob_gas_per_block', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='TARGET_BLOB_GAS_PER_BLOCK', + ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='excess_blob_gas', + ctx=Store())], + value=Call( + func=Name(id='U64', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + If( + test=Compare( + left=Name(id='excess_blob_gas', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Name(id='target_blob_gas_per_block', ctx=Load())]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='excess_blob_gas', + ctx=Store())], + value=BinOp( + left=Name(id='excess_blob_gas', ctx=Load()), + op=Sub(), + right=Name(id='target_blob_gas_per_block', ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='read_base_fee_per_gas', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='data', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='t8n', + annotation=Constant(value='T8N'))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read the base_fee_per_gas from the data. If the base fee is\n not present, it is calculated from the parent block parameters.\n ')), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_gas_used', + ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_gas_limit', + ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_base_fee_per_gas', + ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='base_fee_per_gas', + ctx=Store())], + value=Constant(value=None)), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.london')], + keywords=[]), + body=[ + If( + test=Compare( + left=Constant(value='currentBaseFee'), + ops=[ + In()], + comparators=[ + Name(id='data', ctx=Load())]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='base_fee_per_gas', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='currentBaseFee'), + ctx=Load()), + Name(id='Uint', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_gas_used', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='parentGasUsed'), + ctx=Load()), + Name(id='Uint', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_gas_limit', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='parentGasLimit'), + ctx=Load()), + Name(id='Uint', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_base_fee_per_gas', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='parentBaseFee'), + ctx=Load()), + Name(id='Uint', ctx=Load())], + keywords=[])), + AnnAssign( + target=Name(id='parameters', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='object', ctx=Load()), + ctx=Load()), + value=List( + elts=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_gas_limit', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_gas_limit', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_gas_used', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_base_fee_per_gas', + ctx=Load())], + ctx=Load()), + simple=1), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='base_fee_per_gas', + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='calculate_base_fee_per_gas', + ctx=Load()), + args=[ + Starred( + value=Name(id='parameters', ctx=Load()), + ctx=Load())], + keywords=[]))])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='read_randao', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='data', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='t8n', + annotation=Constant(value='T8N'))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read the randao from the data.\n ')), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='prev_randao', + ctx=Store())], + value=Constant(value=None)), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.paris')], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_random', ctx=Store())], + value=Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='currentRandom'), + ctx=Load())), + If( + test=Call( + func=Attribute( + value=Name(id='current_random', ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Constant(value='0x')], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='current_random', ctx=Store())], + value=Subscript( + value=Name(id='current_random', ctx=Load()), + slice=Slice( + lower=Constant(value=2)), + ctx=Load()))], + orelse=[]), + If( + test=Compare( + left=BinOp( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='current_random', ctx=Load())], + keywords=[]), + op=Mod(), + right=Constant(value=2)), + ops=[ + Eq()], + comparators=[ + Constant(value=1)]), + body=[ + Assign( + targets=[ + Name(id='current_random', ctx=Store())], + value=BinOp( + left=Constant(value='0'), + op=Add(), + right=Name(id='current_random', ctx=Load())))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='prev_randao', + ctx=Store())], + value=Call( + func=Name(id='Bytes32', ctx=Load()), + args=[ + Call( + func=Name(id='left_pad_zero_bytes', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Name(id='current_random', ctx=Load())], + keywords=[]), + Constant(value=32)], + keywords=[])], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='read_withdrawals', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='data', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='t8n', + annotation=Constant(value='T8N'))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read the withdrawals from the data.\n ')), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='withdrawals', + ctx=Store())], + value=Constant(value=None)), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.shanghai')], + keywords=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='withdrawals', + ctx=Store())], + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + GeneratorExp( + elt=Call( + func=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='json_to_withdrawals', + ctx=Load()), + args=[ + Name(id='wd', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='wd', ctx=Store()), + iter=Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='withdrawals'), + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='read_block_difficulty', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='data', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='t8n', + annotation=Constant(value='T8N'))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read the block difficulty from the data.\n If `currentDifficulty` is present, it is used. Otherwise,\n the difficulty is calculated from the parent block.\n ')), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_difficulty', + ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_timestamp', + ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_difficulty', + ctx=Store())], + value=Constant(value=None)), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_ommers_hash', + ctx=Store())], + value=Constant(value=None)), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.paris')], + keywords=[]), + body=[ + Return()], + orelse=[ + If( + test=Compare( + left=Constant(value='currentDifficulty'), + ops=[ + In()], + comparators=[ + Name(id='data', ctx=Load())]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_difficulty', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='currentDifficulty'), + ctx=Load()), + Name(id='Uint', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_timestamp', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='parentTimestamp'), + ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_difficulty', + ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='parentDifficulty'), + ctx=Load()), + Name(id='Uint', ctx=Load())], + keywords=[])), + AnnAssign( + target=Name(id='args', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='object', ctx=Load()), + ctx=Load()), + value=List( + elts=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_timestamp', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_timestamp', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_difficulty', + ctx=Load())], + ctx=Load()), + simple=1), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.byzantium')], + keywords=[]), + body=[ + If( + test=Compare( + left=Constant(value='parentUncleHash'), + ops=[ + In()], + comparators=[ + Name(id='data', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='EMPTY_OMMER_HASH', ctx=Store())], + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + List(elts=[], ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_ommers_hash', + ctx=Store())], + value=Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='parentUncleHash'), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='parent_has_ommers', ctx=Store())], + value=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='parent_ommers_hash', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Name(id='EMPTY_OMMER_HASH', ctx=Load())])), + Expr( + value=Call( + func=Attribute( + value=Name(id='args', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='parent_has_ommers', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='args', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Constant(value=False)], + keywords=[]))])], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_difficulty', + ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='calculate_block_difficulty', + ctx=Load()), + args=[ + Starred( + value=Name(id='args', ctx=Load()), + ctx=Load())], + keywords=[]))])])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='read_block_hashes', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='data', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read the block hashes. Returns a maximum of 256 block hashes.\n ')), + AnnAssign( + target=Name(id='block_hashes', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Any', ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='max_blockhash_count', ctx=Store())], + value=Call( + func=Name(id='min', ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[]), + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load())], + keywords=[])), + For( + target=Name(id='number', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load()), + op=Sub(), + right=Name(id='max_blockhash_count', ctx=Load())), + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load())], + keywords=[]), + body=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Constant(value='blockHashes'), + ops=[ + In()], + comparators=[ + Name(id='data', ctx=Load())]), + Compare( + left=Call( + func=Name(id='str', ctx=Load()), + args=[ + Name(id='number', ctx=Load())], + keywords=[]), + ops=[ + In()], + comparators=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='blockHashes'), + ctx=Load())])]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Name(id='Hash32', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='blockHashes'), + ctx=Load()), + slice=Call( + func=Name(id='str', ctx=Load()), + args=[ + Name(id='number', ctx=Load())], + keywords=[]), + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='block_hashes', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Constant(value=None)], + keywords=[]))])], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_hashes', + ctx=Store())], + value=Name(id='block_hashes', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='read_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='data', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='t8n', + annotation=Constant(value='T8N'))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read the ommers. The ommers data might not have all the details\n needed to obtain the Header.\n ')), + Assign( + targets=[ + Name(id='ommers', ctx=Store())], + value=List(elts=[], ctx=Load())), + If( + test=Compare( + left=Constant(value='ommers'), + ops=[ + In()], + comparators=[ + Name(id='data', ctx=Load())]), + body=[ + For( + target=Name(id='ommer', ctx=Store()), + iter=Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='ommers'), + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='ommers', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Name(id='Ommer', ctx=Load()), + args=[ + Subscript( + value=Name(id='ommer', ctx=Load()), + slice=Constant(value='delta'), + ctx=Load()), + Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='hex_to_address', + ctx=Load()), + args=[ + Subscript( + value=Name(id='ommer', ctx=Load()), + slice=Constant(value='address'), + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='ommers', + ctx=Store())], + value=Name(id='ommers', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/t8n/env.v b/coq/ethereum_spec_tools/evm_tools/t8n/env.v new file mode 100644 index 0000000000..9d3443f6e0 --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/t8n/env.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Define t8n Env class +*) + diff --git a/coq/ethereum_spec_tools/evm_tools/t8n/evm_trace.ast b/coq/ethereum_spec_tools/evm_tools/t8n/evm_trace.ast new file mode 100644 index 0000000000..1a2dd14c09 --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/t8n/evm_trace.ast @@ -0,0 +1,1747 @@ +Module( + body=[ + Expr( + value=Constant(value='\nThe module implements the raw EVM tracer for t8n.\n')), + Import( + names=[ + alias(name='json')]), + Import( + names=[ + alias(name='os')]), + ImportFrom( + module='contextlib', + names=[ + alias(name='ExitStack')], + level=0), + ImportFrom( + module='dataclasses', + names=[ + alias(name='asdict'), + alias(name='dataclass'), + alias(name='is_dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='Protocol'), + alias(name='TextIO'), + alias(name='Union'), + alias(name='runtime_checkable')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.trace', + names=[ + alias(name='EvmStop'), + alias(name='GasAndRefund'), + alias(name='OpEnd'), + alias(name='OpException'), + alias(name='OpStart'), + alias(name='PrecompileEnd'), + alias(name='PrecompileStart'), + alias(name='TraceEvent'), + alias(name='TransactionEnd'), + alias(name='TransactionStart')], + level=0), + Assign( + targets=[ + Name(id='EXCLUDE_FROM_OUTPUT', ctx=Store())], + value=List( + elts=[ + Constant(value='gasCostTraced'), + Constant(value='errorTraced'), + Constant(value='precompile')], + ctx=Load())), + ClassDef( + name='Trace', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The class implements the raw EVM trace.\n ')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='op', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='str', ctx=Load()), + Name(id='int', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gasCost', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memSize', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='returnData', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='opName', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gasCostTraced', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + value=Constant(value=False), + simple=1), + AnnAssign( + target=Name(id='errorTraced', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + value=Constant(value=False), + simple=1), + AnnAssign( + target=Name(id='precompile', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + value=Constant(value=False), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + value=Constant(value=None), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='FinalTrace', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The class implements final trace for a tx.\n ')), + AnnAssign( + target=Name(id='output', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gasUsed', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='error', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + value=Constant(value=None), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='gas_used', + annotation=Name(id='int', ctx=Load())), + arg( + arg='output', + annotation=Name(id='bytes', ctx=Load())), + arg( + arg='error', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Exception', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='output', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='output', ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='gasUsed', + ctx=Store())], + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Name(id='gas_used', ctx=Load())], + keywords=[])), + If( + test=Name(id='error', ctx=Load()), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='error', + ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='error', ctx=Load())], + keywords=[]), + attr='__name__', + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Environment', + bases=[ + Name(id='Protocol', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The class implements the environment interface for trace.\n ')), + AnnAssign( + target=Name(id='traces', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Constant(value='Trace'), + Constant(value='FinalTrace')], + ctx=Load()), + ctx=Load()), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='runtime_checkable', ctx=Load())]), + ClassDef( + name='Message', + bases=[ + Name(id='Protocol', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The class implements the message interface for trace.\n ')), + AnnAssign( + target=Name(id='depth', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='parent_evm', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Constant(value='Evm'), + ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='runtime_checkable', ctx=Load())]), + ClassDef( + name='EvmWithoutReturnData', + bases=[ + Name(id='Protocol', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The class implements the EVM interface for pre-byzantium forks trace.\n ')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='runtime_checkable', ctx=Load())]), + ClassDef( + name='EvmWithReturnData', + bases=[ + Name(id='Protocol', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The class implements the EVM interface for post-byzantium forks trace.\n ')), + AnnAssign( + target=Name(id='pc', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='stack', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='memory', ctx=Store()), + annotation=Name(id='bytearray', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='code', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='gas_left', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='env', ctx=Store()), + annotation=Name(id='Environment', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='refund_counter', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='running', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='Message', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='return_data', ctx=Store()), + annotation=Name(id='Bytes', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='runtime_checkable', ctx=Load())]), + Assign( + targets=[ + Name(id='Evm', ctx=Store())], + value=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='EvmWithoutReturnData', ctx=Load()), + Name(id='EvmWithReturnData', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='evm_trace', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='evm', + annotation=Name(id='object', ctx=Load())), + arg( + arg='event', + annotation=Name(id='TraceEvent', ctx=Load())), + arg( + arg='trace_memory', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='trace_stack', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='trace_return_data', + annotation=Name(id='bool', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=False), + Constant(value=True), + Constant(value=False)]), + body=[ + Expr( + value=Constant(value='\n Create a trace of the event.\n ')), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Tuple( + elts=[ + Name(id='EvmWithoutReturnData', ctx=Load()), + Name(id='EvmWithReturnData', ctx=Load())], + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='last_trace', ctx=Store())], + value=Constant(value=None)), + If( + test=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='traces', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='last_trace', ctx=Store())], + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='traces', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='refund_counter', ctx=Store())], + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load())), + While( + test=Compare( + left=Name(id='parent_evm', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + AugAssign( + target=Name(id='refund_counter', ctx=Store()), + op=Add(), + value=Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='refund_counter', + ctx=Load())), + Assign( + targets=[ + Name(id='parent_evm', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='parent_evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='parent_evm', + ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='len_memory', ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='return_data', ctx=Store())], + value=Constant(value=None)), + If( + test=BoolOp( + op=And(), + values=[ + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Name(id='EvmWithReturnData', ctx=Load())], + keywords=[]), + Name(id='trace_return_data', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='return_data', ctx=Store())], + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='return_data', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[])))], + orelse=[]), + Assign( + targets=[ + Name(id='memory', ctx=Store())], + value=Constant(value=None)), + If( + test=BoolOp( + op=And(), + values=[ + Name(id='trace_memory', ctx=Load()), + Compare( + left=Name(id='len_memory', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)])]), + body=[ + Assign( + targets=[ + Name(id='memory', ctx=Store())], + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='memory', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[])))], + orelse=[]), + Assign( + targets=[ + Name(id='stack', ctx=Store())], + value=Constant(value=None)), + If( + test=Name(id='trace_stack', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='stack', ctx=Store())], + value=ListComp( + elt=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='i', ctx=Store()), + iter=Attribute( + value=Name(id='evm', ctx=Load()), + attr='stack', + ctx=Load()), + ifs=[], + is_async=0)]))], + orelse=[]), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='event', ctx=Load()), + Name(id='TransactionStart', ctx=Load())], + keywords=[]), + body=[ + Pass()], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='event', ctx=Load()), + Name(id='TransactionEnd', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='final_trace', ctx=Store())], + value=Call( + func=Name(id='FinalTrace', ctx=Load()), + args=[ + Attribute( + value=Name(id='event', ctx=Load()), + attr='gas_used', + ctx=Load()), + Attribute( + value=Name(id='event', ctx=Load()), + attr='output', + ctx=Load()), + Attribute( + value=Name(id='event', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='traces', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='final_trace', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='event', ctx=Load()), + Name(id='PrecompileStart', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='new_trace', ctx=Store())], + value=Call( + func=Name(id='Trace', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])), + keyword( + arg='op', + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='event', ctx=Load()), + attr='address', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[]), + attr='lstrip', + ctx=Load()), + args=[ + Constant(value='0')], + keywords=[]))), + keyword( + arg='gas', + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + keyword( + arg='gasCost', + value=Constant(value='0x0')), + keyword( + arg='memory', + value=Name(id='memory', ctx=Load())), + keyword( + arg='memSize', + value=Name(id='len_memory', ctx=Load())), + keyword( + arg='stack', + value=Name(id='stack', ctx=Load())), + keyword( + arg='returnData', + value=Name(id='return_data', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load())], + keywords=[]), + op=Add(), + right=Constant(value=1))), + keyword( + arg='refund', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='opName', + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='event', ctx=Load()), + attr='address', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[]), + attr='lstrip', + ctx=Load()), + args=[ + Constant(value='0')], + keywords=[]))), + keyword( + arg='precompile', + value=Constant(value=True))])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='traces', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='new_trace', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='event', ctx=Load()), + Name(id='PrecompileEnd', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='last_trace', ctx=Load()), + Name(id='Trace', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='last_trace', ctx=Load()), + attr='gasCostTraced', + ctx=Store())], + value=Constant(value=True)), + Assign( + targets=[ + Attribute( + value=Name(id='last_trace', ctx=Load()), + attr='errorTraced', + ctx=Store())], + value=Constant(value=True))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='event', ctx=Load()), + Name(id='OpStart', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='event', ctx=Load()), + attr='op', + ctx=Load()), + attr='value', + ctx=Load())), + If( + test=Compare( + left=Name(id='op', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='InvalidOpcode')]), + body=[ + Assign( + targets=[ + Name(id='op', ctx=Store())], + value=Constant(value='Invalid'))], + orelse=[]), + Assign( + targets=[ + Name(id='new_trace', ctx=Store())], + value=Call( + func=Name(id='Trace', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])), + keyword( + arg='op', + value=Name(id='op', ctx=Load())), + keyword( + arg='gas', + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + keyword( + arg='gasCost', + value=Constant(value='0x0')), + keyword( + arg='memory', + value=Name(id='memory', ctx=Load())), + keyword( + arg='memSize', + value=Name(id='len_memory', ctx=Load())), + keyword( + arg='stack', + value=Name(id='stack', ctx=Load())), + keyword( + arg='returnData', + value=Name(id='return_data', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load())], + keywords=[]), + op=Add(), + right=Constant(value=1))), + keyword( + arg='refund', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='opName', + value=Subscript( + value=Call( + func=Attribute( + value=Call( + func=Name(id='str', ctx=Load()), + args=[ + Attribute( + value=Name(id='event', ctx=Load()), + attr='op', + ctx=Load())], + keywords=[]), + attr='split', + ctx=Load()), + args=[ + Constant(value='.')], + keywords=[]), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='traces', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='new_trace', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='event', ctx=Load()), + Name(id='OpEnd', ctx=Load())], + keywords=[]), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='last_trace', ctx=Load()), + Name(id='Trace', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='last_trace', ctx=Load()), + attr='gasCostTraced', + ctx=Store())], + value=Constant(value=True)), + Assign( + targets=[ + Attribute( + value=Name(id='last_trace', ctx=Load()), + attr='errorTraced', + ctx=Store())], + value=Constant(value=True))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='event', ctx=Load()), + Name(id='OpException', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Name(id='last_trace', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='last_trace', ctx=Load()), + Name(id='Trace', ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + UnaryOp( + op=Not(), + operand=Name(id='last_trace', ctx=Load())), + Attribute( + value=Name(id='last_trace', ctx=Load()), + attr='errorTraced', + ctx=Load()), + Compare( + left=Attribute( + value=Name(id='last_trace', ctx=Load()), + attr='depth', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load())])]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='hasattr', ctx=Load()), + args=[ + Attribute( + value=Name(id='event', ctx=Load()), + attr='error', + ctx=Load()), + Constant(value='code')], + keywords=[])), + body=[ + Assign( + targets=[ + Name(id='name', ctx=Store())], + value=Attribute( + value=Attribute( + value=Attribute( + value=Name(id='event', ctx=Load()), + attr='error', + ctx=Load()), + attr='__class__', + ctx=Load()), + attr='__name__', + ctx=Load())), + Raise( + exc=Call( + func=Name(id='TypeError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='OpException event error type `'), + FormattedValue( + value=Name(id='name', ctx=Load()), + conversion=-1), + Constant(value='` does not have code')])], + keywords=[]), + cause=Attribute( + value=Name(id='event', ctx=Load()), + attr='error', + ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='new_trace', ctx=Store())], + value=Call( + func=Name(id='Trace', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='pc', + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='pc', + ctx=Load())], + keywords=[])), + keyword( + arg='op', + value=Attribute( + value=Attribute( + value=Name(id='event', ctx=Load()), + attr='error', + ctx=Load()), + attr='code', + ctx=Load())), + keyword( + arg='gas', + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='gas_left', + ctx=Load())], + keywords=[])), + keyword( + arg='gasCost', + value=Constant(value='0x0')), + keyword( + arg='memory', + value=Name(id='memory', ctx=Load())), + keyword( + arg='memSize', + value=Name(id='len_memory', ctx=Load())), + keyword( + arg='stack', + value=Name(id='stack', ctx=Load())), + keyword( + arg='returnData', + value=Name(id='return_data', ctx=Load())), + keyword( + arg='depth', + value=BinOp( + left=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='message', + ctx=Load()), + attr='depth', + ctx=Load())], + keywords=[]), + op=Add(), + right=Constant(value=1))), + keyword( + arg='refund', + value=Name(id='refund_counter', ctx=Load())), + keyword( + arg='opName', + value=Constant(value='InvalidOpcode')), + keyword( + arg='gasCostTraced', + value=Constant(value=True)), + keyword( + arg='errorTraced', + value=Constant(value=True)), + keyword( + arg='error', + value=Attribute( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Attribute( + value=Name(id='event', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[]), + attr='__name__', + ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='traces', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='new_trace', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='last_trace', ctx=Load()), + attr='errorTraced', + ctx=Load())), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='last_trace', ctx=Load()), + attr='error', + ctx=Store())], + value=Attribute( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Attribute( + value=Name(id='event', ctx=Load()), + attr='error', + ctx=Load())], + keywords=[]), + attr='__name__', + ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='last_trace', ctx=Load()), + attr='errorTraced', + ctx=Store())], + value=Constant(value=True))], + orelse=[])])], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='event', ctx=Load()), + Name(id='EvmStop', ctx=Load())], + keywords=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='evm', ctx=Load()), + attr='running', + ctx=Load())), + body=[ + Return()], + orelse=[ + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='evm', ctx=Load()), + attr='code', + ctx=Load())], + keywords=[]), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return()], + orelse=[ + Expr( + value=Call( + func=Name(id='evm_trace', ctx=Load()), + args=[ + Name(id='evm', ctx=Load()), + Call( + func=Name(id='OpStart', ctx=Load()), + args=[ + Attribute( + value=Name(id='event', ctx=Load()), + attr='op', + ctx=Load())], + keywords=[]), + Name(id='trace_memory', ctx=Load()), + Name(id='trace_stack', ctx=Load()), + Name(id='trace_return_data', ctx=Load())], + keywords=[]))])])], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='event', ctx=Load()), + Name(id='GasAndRefund', ctx=Load())], + keywords=[]), + body=[ + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Attribute( + value=Name(id='evm', ctx=Load()), + attr='env', + ctx=Load()), + attr='traces', + ctx=Load())), + body=[ + Return()], + orelse=[]), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='last_trace', ctx=Load()), + Name(id='Trace', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='last_trace', ctx=Load()), + attr='gasCostTraced', + ctx=Load())), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='last_trace', ctx=Load()), + attr='gasCost', + ctx=Store())], + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Attribute( + value=Name(id='event', ctx=Load()), + attr='gas_cost', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='last_trace', ctx=Load()), + attr='refund', + ctx=Store())], + value=Name(id='refund_counter', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='last_trace', ctx=Load()), + attr='gasCostTraced', + ctx=Store())], + value=Constant(value=True))], + orelse=[])], + orelse=[])])])])])])])])])], + decorator_list=[], + returns=Constant(value=None)), + ClassDef( + name='_TraceJsonEncoder', + bases=[ + Attribute( + value=Name(id='json', ctx=Load()), + attr='JSONEncoder', + ctx=Load())], + keywords=[], + body=[ + FunctionDef( + name='retain', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='k', + annotation=Name(id='str', ctx=Load())), + arg( + arg='v', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='object', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='k', ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='EXCLUDE_FROM_OUTPUT', ctx=Load())]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=Compare( + left=Name(id='k', ctx=Load()), + ops=[ + In()], + comparators=[ + Tuple( + elts=[ + Constant(value='pc'), + Constant(value='gas'), + Constant(value='gasCost'), + Constant(value='refund')], + ctx=Load())]), + body=[ + If( + test=BoolOp( + op=And(), + values=[ + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='v', ctx=Load()), + Name(id='str', ctx=Load())], + keywords=[]), + Compare( + left=Call( + func=Attribute( + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='v', ctx=Load()), + Constant(value=0)], + keywords=[]), + attr='bit_length', + ctx=Load()), + args=[], + keywords=[]), + ops=[ + Gt()], + comparators=[ + Constant(value=64)])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[])], + orelse=[]), + Return( + value=Constant(value=True))], + decorator_list=[ + Name(id='staticmethod', ctx=Load())], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='default', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='obj', + annotation=Name(id='object', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='is_dataclass', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[])), + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='obj', ctx=Load()), + Name(id='type', ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='default', + ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='trace', ctx=Store())], + value=DictComp( + key=Name(id='k', ctx=Load()), + value=Name(id='v', ctx=Load()), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='v', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Call( + func=Name(id='asdict', ctx=Load()), + args=[ + Name(id='obj', ctx=Load())], + keywords=[]), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[ + Call( + func=Attribute( + value=Name(id='_TraceJsonEncoder', ctx=Load()), + attr='retain', + ctx=Load()), + args=[ + Name(id='k', ctx=Load()), + Name(id='v', ctx=Load())], + keywords=[])], + is_async=0)])), + Return( + value=Name(id='trace', ctx=Load()))], + decorator_list=[], + returns=Name(id='object', ctx=Load()))], + decorator_list=[]), + FunctionDef( + name='output_op_trace', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='trace', + annotation=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Trace', ctx=Load()), + Name(id='FinalTrace', ctx=Load())], + ctx=Load()), + ctx=Load())), + arg( + arg='json_file', + annotation=Name(id='TextIO', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Output a single trace to a json file.\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dump', + ctx=Load()), + args=[ + Name(id='trace', ctx=Load()), + Name(id='json_file', ctx=Load())], + keywords=[ + keyword( + arg='separators', + value=Tuple( + elts=[ + Constant(value=','), + Constant(value=':')], + ctx=Load())), + keyword( + arg='cls', + value=Name(id='_TraceJsonEncoder', ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='json_file', ctx=Load()), + attr='write', + ctx=Load()), + args=[ + Constant(value='\n')], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='output_traces', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='traces', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Trace', ctx=Load()), + Name(id='FinalTrace', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())), + arg( + arg='tx_index', + annotation=Name(id='int', ctx=Load())), + arg( + arg='tx_hash', + annotation=Name(id='bytes', ctx=Load())), + arg( + arg='output_basedir', + annotation=BinOp( + left=Name(id='str', ctx=Load()), + op=BitOr(), + right=Name(id='TextIO', ctx=Load())))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value='.')]), + body=[ + Expr( + value=Constant(value='\n Output the traces to a json file.\n ')), + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='ExitStack', ctx=Load()), + args=[], + keywords=[]), + optional_vars=Name(id='stack', ctx=Store()))], + body=[ + AnnAssign( + target=Name(id='json_file', ctx=Store()), + annotation=Name(id='TextIO', ctx=Load()), + simple=1), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='output_basedir', ctx=Load()), + Name(id='str', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='tx_hash_str', ctx=Store())], + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='tx_hash', ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[]))), + Assign( + targets=[ + Name(id='output_path', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='os', ctx=Load()), + attr='path', + ctx=Load()), + attr='join', + ctx=Load()), + args=[ + Name(id='output_basedir', ctx=Load()), + JoinedStr( + values=[ + Constant(value='trace-'), + FormattedValue( + value=Name(id='tx_index', ctx=Load()), + conversion=-1), + Constant(value='-'), + FormattedValue( + value=Name(id='tx_hash_str', ctx=Load()), + conversion=-1), + Constant(value='.jsonl')])], + keywords=[])), + Assign( + targets=[ + Name(id='json_file', ctx=Store())], + value=Call( + func=Name(id='open', ctx=Load()), + args=[ + Name(id='output_path', ctx=Load()), + Constant(value='w')], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stack', ctx=Load()), + attr='push', + ctx=Load()), + args=[ + Name(id='json_file', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='json_file', ctx=Store())], + value=Name(id='output_basedir', ctx=Load()))]), + For( + target=Name(id='trace', ctx=Store()), + iter=Name(id='traces', ctx=Load()), + body=[ + If( + test=Call( + func=Name(id='getattr', ctx=Load()), + args=[ + Name(id='trace', ctx=Load()), + Constant(value='precompile'), + Constant(value=False)], + keywords=[]), + body=[ + Continue()], + orelse=[]), + Expr( + value=Call( + func=Name(id='output_op_trace', ctx=Load()), + args=[ + Name(id='trace', ctx=Load()), + Name(id='json_file', ctx=Load())], + keywords=[]))], + orelse=[])])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/t8n/evm_trace.v b/coq/ethereum_spec_tools/evm_tools/t8n/evm_trace.v new file mode 100644 index 0000000000..aef7ac65b1 --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/t8n/evm_trace.v @@ -0,0 +1,61 @@ +(* Generated *) +(* +The module implements the raw EVM tracer for t8n. +*) + + +Definition evm_trace (evm : object) (event : TraceEvent) (trace_memory : bool) (trace_stack : bool) (trace_return_data : bool) : M unit := + (* + Create a trace of the event. + *) + (* TODO statement *) + do* M.assign "last_trace" [[ + tt in + ]] in + (* TODO statement *) + do* M.assign "refund_counter" [[ + M.get_field ~(| evm, "refund_counter" |) in + ]] in + do* M.assign "parent_evm" [[ + M.get_field ~(| M.get_field ~(| evm, "message" |), "parent_evm" |) in + ]] in + (* TODO statement *) + do* M.assign "len_memory" [[ + M.get_local ~(| "len" |) ~(| + M.get_field ~(| evm, "memory" |) + |) in + ]] in + do* M.assign "return_data" [[ + tt in + ]] in + (* TODO statement *) + do* M.assign "memory" [[ + tt in + ]] in + (* TODO statement *) + do* M.assign "stack" [[ + tt in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition output_op_trace (trace : (* TODO type *)) (json_file : TextIO) : M unit := + (* + Output a single trace to a json file. + *) + do* [[ M.get_field ~(| M.get_local ~(| "json" |), "dump" |) ~(| + trace, + json_file + |) ]] in + do* [[ M.get_field ~(| json_file, "write" |) ~(| + (* TODO constant *) + |) ]] in + M.pure tt. + +Definition output_traces (traces : (* TODO type *)) (tx_index : int) (tx_hash : bytes) (output_basedir : (* TODO type *)) : M unit := + (* + Output the traces to a json file. + *) + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum_spec_tools/evm_tools/t8n/t8n_types.ast b/coq/ethereum_spec_tools/evm_tools/t8n/t8n_types.ast new file mode 100644 index 0000000000..d80daa3b0f --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/t8n/t8n_types.ast @@ -0,0 +1,2378 @@ +Module( + body=[ + Expr( + value=Constant(value='\nDefine the types used by the t8n tool.\n')), + Import( + names=[ + alias(name='json')]), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='TYPE_CHECKING'), + alias(name='Any'), + alias(name='Dict'), + alias(name='Iterator'), + alias(name='List'), + alias(name='Optional'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum', + names=[ + alias(name='rlp')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='keccak256')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes'), + alias(name='hex_to_u256'), + alias(name='hex_to_uint')], + level=0), + ImportFrom( + module='loaders.transaction_loader', + names=[ + alias(name='TransactionLoad'), + alias(name='UnsupportedTx')], + level=2), + ImportFrom( + module='utils', + names=[ + alias(name='FatalException'), + alias(name='secp256k1_sign')], + level=2), + If( + test=Name(id='TYPE_CHECKING', ctx=Load()), + body=[ + ImportFrom( + names=[ + alias(name='T8N')], + level=1)], + orelse=[]), + ClassDef( + name='Alloc', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n The alloc (state) type for the t8n tool.\n ')), + AnnAssign( + target=Name(id='state', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_backup', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='t8n', + annotation=Constant(value='T8N')), + arg( + arg='stdin', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Dict', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='Read the alloc file and return the state.')), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='options', + ctx=Load()), + attr='input_alloc', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='stdin')]), + body=[ + Assert( + test=Compare( + left=Name(id='stdin', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Subscript( + value=Name(id='stdin', ctx=Load()), + slice=Constant(value='alloc'), + ctx=Load()))], + orelse=[ + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='open', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='options', + ctx=Load()), + attr='input_alloc', + ctx=Load()), + Constant(value='r')], + keywords=[]), + optional_vars=Name(id='f', ctx=Store()))], + body=[ + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='f', ctx=Load())], + keywords=[]))])]), + For( + target=Tuple( + elts=[ + Name(id='address', ctx=Store()), + Name(id='account', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='data', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='key', ctx=Store()), + Name(id='value', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='account', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='key', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='storage')]), + UnaryOp( + op=Not(), + operand=Name(id='value', ctx=Load()))]), + body=[ + Continue()], + orelse=[ + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Constant(value='0x')], + keywords=[])), + body=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='data', ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load()), + slice=Name(id='key', ctx=Load()), + ctx=Store())], + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[])))], + orelse=[])])], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Name(id='state', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='json_to_state', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='fork_module', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='dao_fork')]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='apply_dao', + ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='state', + ctx=Store())], + value=Name(id='state', ctx=Load()))], + decorator_list=[]), + FunctionDef( + name='to_json', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Encode the state to JSON')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Dict(keys=[], values=[])), + For( + target=Tuple( + elts=[ + Name(id='address', ctx=Store()), + Name(id='account', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='state', + ctx=Load()), + attr='_main_trie', + ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + AnnAssign( + target=Name(id='account_data', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='str', ctx=Load()), + Name(id='Any', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + If( + test=Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load()), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='account_data', ctx=Load()), + slice=Constant(value='balance'), + ctx=Store())], + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='balance', + ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load()), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='account_data', ctx=Load()), + slice=Constant(value='nonce'), + ctx=Store())], + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Attribute( + value=Name(id='account', ctx=Load()), + attr='nonce', + ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='account_data', ctx=Load()), + slice=Constant(value='code'), + ctx=Store())], + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='account', ctx=Load()), + attr='code', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[])))], + orelse=[]), + If( + test=Compare( + left=Name(id='address', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='state', + ctx=Load()), + attr='_storage_tries', + ctx=Load())]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='account_data', ctx=Load()), + slice=Constant(value='storage'), + ctx=Store())], + value=DictComp( + key=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='k', ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[])), + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Name(id='v', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='v', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='state', + ctx=Load()), + attr='_storage_tries', + ctx=Load()), + slice=Name(id='address', ctx=Load()), + ctx=Load()), + attr='_data', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)]))], + orelse=[]), + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='address', ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[])), + ctx=Store())], + value=Name(id='account_data', ctx=Load()))], + orelse=[]), + Return( + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Name(id='Any', ctx=Load()))], + decorator_list=[]), + ClassDef( + name='Txs', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Read the transactions file, sort out the valid transactions and\n return a list of transactions.\n ')), + AnnAssign( + target=Name(id='rejected_txs', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='int', ctx=Load()), + Name(id='str', ctx=Load())], + ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='successful_txs', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Any', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='successful_receipts', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Any', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='all_txs', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Any', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='t8n', ctx=Store()), + annotation=Constant(value='T8N'), + simple=1), + AnnAssign( + target=Name(id='data', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='rlp_input', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='t8n', + annotation=Constant(value='T8N')), + arg( + arg='stdin', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Dict', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='t8n', + ctx=Store())], + value=Name(id='t8n', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='rejected_txs', + ctx=Store())], + value=Dict(keys=[], values=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='successful_txs', + ctx=Store())], + value=List(elts=[], ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='successful_receipts', + ctx=Store())], + value=List(elts=[], ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='rlp_input', + ctx=Store())], + value=Constant(value=False)), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='all_txs', + ctx=Store())], + value=List(elts=[], ctx=Load())), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='options', + ctx=Load()), + attr='input_txs', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='stdin')]), + body=[ + Assert( + test=Compare( + left=Name(id='stdin', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Subscript( + value=Name(id='stdin', ctx=Load()), + slice=Constant(value='txs'), + ctx=Load()))], + orelse=[ + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='open', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='options', + ctx=Load()), + attr='input_txs', + ctx=Load()), + Constant(value='r')], + keywords=[]), + optional_vars=Name(id='f', ctx=Store()))], + body=[ + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='f', ctx=Load())], + keywords=[]))])]), + If( + test=Compare( + left=Name(id='data', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='data', + ctx=Store())], + value=List(elts=[], ctx=Load()))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='data', ctx=Load()), + Name(id='str', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='rlp_input', + ctx=Store())], + value=Constant(value=True)), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='data', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode', + ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='data', + ctx=Store())], + value=Name(id='data', ctx=Load()))])])], + decorator_list=[]), + FunctionDef( + name='transactions', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read the transactions file and return a list of transactions.\n Can read from JSON or RLP.\n ')), + For( + target=Tuple( + elts=[ + Name(id='idx', ctx=Store()), + Name(id='raw_tx', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='data', + ctx=Load())], + keywords=[]), + body=[ + Try( + body=[ + If( + test=Attribute( + value=Name(id='self', ctx=Load()), + attr='rlp_input', + ctx=Load()), + body=[ + Expr( + value=Yield( + value=Tuple( + elts=[ + Name(id='idx', ctx=Load()), + Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='parse_rlp_tx', + ctx=Load()), + args=[ + Name(id='raw_tx', ctx=Load())], + keywords=[])], + ctx=Load())))], + orelse=[ + Expr( + value=Yield( + value=Tuple( + elts=[ + Name(id='idx', ctx=Load()), + Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='parse_json_tx', + ctx=Load()), + args=[ + Name(id='raw_tx', ctx=Load())], + keywords=[])], + ctx=Load())))])], + handlers=[ + ExceptHandler( + type=Name(id='UnsupportedTx', ctx=Load()), + name='e', + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='t8n', + ctx=Load()), + attr='logger', + ctx=Load()), + attr='warning', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Unsupported transaction type '), + FormattedValue( + value=Name(id='idx', ctx=Load()), + conversion=-1), + Constant(value=': '), + FormattedValue( + value=Attribute( + value=Name(id='e', ctx=Load()), + attr='error_message', + ctx=Load()), + conversion=-1)])], + keywords=[])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='rejected_txs', + ctx=Load()), + slice=Name(id='idx', ctx=Load()), + ctx=Store())], + value=JoinedStr( + values=[ + Constant(value='Unsupported transaction type: '), + FormattedValue( + value=Attribute( + value=Name(id='e', ctx=Load()), + attr='error_message', + ctx=Load()), + conversion=-1)])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='all_txs', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Attribute( + value=Name(id='e', ctx=Load()), + attr='encoded_params', + ctx=Load())], + keywords=[]))]), + ExceptHandler( + type=Name(id='Exception', ctx=Load()), + name='e', + body=[ + Assign( + targets=[ + Name(id='msg', ctx=Store())], + value=JoinedStr( + values=[ + Constant(value='Failed to parse transaction '), + FormattedValue( + value=Name(id='idx', ctx=Load()), + conversion=-1), + Constant(value=': '), + FormattedValue( + value=Call( + func=Name(id='str', ctx=Load()), + args=[ + Name(id='e', ctx=Load())], + keywords=[]), + conversion=-1)])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='t8n', + ctx=Load()), + attr='logger', + ctx=Load()), + attr='warning', + ctx=Load()), + args=[ + Name(id='msg', ctx=Load())], + keywords=[ + keyword( + arg='exc_info', + value=Name(id='e', ctx=Load()))])), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='rejected_txs', + ctx=Load()), + slice=Name(id='idx', ctx=Load()), + ctx=Store())], + value=Name(id='msg', ctx=Load()))])], + orelse=[], + finalbody=[])], + orelse=[])], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Subscript( + value=Name(id='Iterator', ctx=Load()), + slice=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='int', ctx=Load()), + Name(id='Any', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())), + FunctionDef( + name='parse_rlp_tx', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='raw_tx', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read transactions from RLP.\n ')), + Assign( + targets=[ + Name(id='t8n', ctx=Store())], + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='t8n', + ctx=Load())), + Assign( + targets=[ + Name(id='tx_rlp', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='raw_tx', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.berlin')], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='raw_tx', ctx=Load()), + Name(id='Bytes', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='transaction', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='decode_transaction', + ctx=Load()), + args=[ + Name(id='raw_tx', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='all_txs', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='raw_tx', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='transaction', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='LegacyTransaction', + ctx=Load()), + Name(id='tx_rlp', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='all_txs', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='transaction', ctx=Load())], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='transaction', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Transaction', + ctx=Load()), + Name(id='tx_rlp', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='all_txs', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='transaction', ctx=Load())], + keywords=[]))]), + Return( + value=Name(id='transaction', ctx=Load()))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='parse_json_tx', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='raw_tx', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Read the transactions from json.\n If a transaction is unsigned but has a `secretKey` field, the\n transaction will be signed.\n ')), + Assign( + targets=[ + Name(id='t8n', ctx=Store())], + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='t8n', + ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='raw_tx', ctx=Load()), + slice=Constant(value='gasLimit'), + ctx=Store())], + value=Subscript( + value=Name(id='raw_tx', ctx=Load()), + slice=Constant(value='gas'), + ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='raw_tx', ctx=Load()), + slice=Constant(value='data'), + ctx=Store())], + value=Subscript( + value=Name(id='raw_tx', ctx=Load()), + slice=Constant(value='input'), + ctx=Load())), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Constant(value='to'), + ops=[ + NotIn()], + comparators=[ + Name(id='raw_tx', ctx=Load())]), + Compare( + left=Subscript( + value=Name(id='raw_tx', ctx=Load()), + slice=Constant(value='to'), + ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)])]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='raw_tx', ctx=Load()), + slice=Constant(value='to'), + ctx=Store())], + value=Constant(value=''))], + orelse=[]), + Assign( + targets=[ + Subscript( + value=Name(id='raw_tx', ctx=Load()), + slice=Constant(value='v'), + ctx=Store())], + value=BoolOp( + op=Or(), + values=[ + Call( + func=Attribute( + value=Name(id='raw_tx', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='v')], + keywords=[]), + Call( + func=Attribute( + value=Name(id='raw_tx', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='y_parity')], + keywords=[]), + Constant(value='0x00')])), + Assign( + targets=[ + Subscript( + value=Name(id='raw_tx', ctx=Load()), + slice=Constant(value='r'), + ctx=Store())], + value=BoolOp( + op=Or(), + values=[ + Call( + func=Attribute( + value=Name(id='raw_tx', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='r')], + keywords=[]), + Constant(value='0x00')])), + Assign( + targets=[ + Subscript( + value=Name(id='raw_tx', ctx=Load()), + slice=Constant(value='s'), + ctx=Store())], + value=BoolOp( + op=Or(), + values=[ + Call( + func=Attribute( + value=Name(id='raw_tx', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='s')], + keywords=[]), + Constant(value='0x00')])), + Assign( + targets=[ + Name(id='v', ctx=Store())], + value=Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='raw_tx', ctx=Load()), + slice=Constant(value='v'), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='r', ctx=Store())], + value=Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='raw_tx', ctx=Load()), + slice=Constant(value='r'), + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='raw_tx', ctx=Load()), + slice=Constant(value='s'), + ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Constant(value='secretKey'), + ops=[ + In()], + comparators=[ + Name(id='raw_tx', ctx=Load())]), + Compare( + left=Name(id='v', ctx=Load()), + ops=[ + Eq(), + Eq(), + Eq()], + comparators=[ + Name(id='r', ctx=Load()), + Name(id='s', ctx=Load()), + Constant(value=0)])]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='sign_transaction', + ctx=Load()), + args=[ + Name(id='raw_tx', ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='tx', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='TransactionLoad', ctx=Load()), + args=[ + Name(id='raw_tx', ctx=Load()), + Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load())], + keywords=[]), + attr='read', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='all_txs', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.berlin')], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='transaction', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='decode_transaction', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='transaction', ctx=Store())], + value=Name(id='tx', ctx=Load()))]), + Return( + value=Name(id='transaction', ctx=Load()))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='add_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='tx', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add a transaction to the list of successful transactions.\n ')), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='t8n', + ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.berlin')], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='successful_txs', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='t8n', + ctx=Load()), + attr='fork', + ctx=Load()), + attr='encode_transaction', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='successful_txs', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='get_tx_hash', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='tx', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the transaction hash of a transaction.\n ')), + If( + test=BoolOp( + op=And(), + values=[ + Call( + func=Attribute( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='t8n', + ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.berlin')], + keywords=[]), + UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Attribute( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='t8n', + ctx=Load()), + attr='fork', + ctx=Load()), + attr='LegacyTransaction', + ctx=Load())], + keywords=[]))]), + body=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='t8n', + ctx=Load()), + attr='fork', + ctx=Load()), + attr='encode_transaction', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[ + Return( + value=Call( + func=Name(id='keccak256', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[], + returns=Name(id='bytes', ctx=Load())), + FunctionDef( + name='add_receipt', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='tx', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='gas_consumed', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Add t8n receipt info for valid tx\n ')), + Assign( + targets=[ + Name(id='tx_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='get_tx_hash', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Dict( + keys=[ + Constant(value='transactionHash'), + Constant(value='gasUsed')], + values=[ + BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='tx_hash', ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[])), + Call( + func=Name(id='hex', ctx=Load()), + args=[ + Name(id='gas_consumed', ctx=Load())], + keywords=[])])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='successful_receipts', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='sign_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='json_tx', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sign a transaction. This function will be invoked if a `secretKey`\n is provided in the transaction.\n Post spurious dragon, the transaction is signed according to EIP-155\n if the protected flag is missing or set to true.\n ')), + Assign( + targets=[ + Name(id='t8n', ctx=Store())], + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='t8n', + ctx=Load())), + Assign( + targets=[ + Name(id='protected', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json_tx', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='protected'), + Constant(value=True)], + keywords=[])), + Assign( + targets=[ + Name(id='tx', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='TransactionLoad', ctx=Load()), + args=[ + Name(id='json_tx', ctx=Load()), + Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load())], + keywords=[]), + attr='read', + ctx=Load()), + args=[], + keywords=[])), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx', ctx=Load()), + Name(id='bytes', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='tx_decoded', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='decode_transaction', + ctx=Load()), + args=[ + Name(id='tx', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='tx_decoded', ctx=Store())], + value=Name(id='tx', ctx=Load()))]), + Assign( + targets=[ + Name(id='secret_key', ctx=Store())], + value=Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Subscript( + value=Subscript( + value=Name(id='json_tx', ctx=Load()), + slice=Constant(value='secretKey'), + ctx=Load()), + slice=Slice( + lower=Constant(value=2)), + ctx=Load())], + keywords=[])), + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.berlin')], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='Transaction', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='LegacyTransaction', + ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='Transaction', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='Transaction', + ctx=Load()))]), + AnnAssign( + target=Name(id='v_addend', ctx=Store()), + annotation=Name(id='U256', ctx=Load()), + simple=1), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx_decoded', ctx=Load()), + Name(id='Transaction', ctx=Load())], + keywords=[]), + body=[ + If( + test=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='is_after_fork', + ctx=Load()), + args=[ + Constant(value='ethereum.spurious_dragon')], + keywords=[]), + body=[ + If( + test=Name(id='protected', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='signing_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='signing_hash_155', + ctx=Load()), + args=[ + Name(id='tx_decoded', ctx=Load()), + Call( + func=Name(id='U64', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='v_addend', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=37)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='signing_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='signing_hash_pre155', + ctx=Load()), + args=[ + Name(id='tx_decoded', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v_addend', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[]))])], + orelse=[ + Assign( + targets=[ + Name(id='signing_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='signing_hash', + ctx=Load()), + args=[ + Name(id='tx_decoded', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v_addend', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=27)], + keywords=[]))])], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx_decoded', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='AccessListTransaction', + ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='signing_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='signing_hash_2930', + ctx=Load()), + args=[ + Name(id='tx_decoded', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v_addend', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx_decoded', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='FeeMarketTransaction', + ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='signing_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='signing_hash_1559', + ctx=Load()), + args=[ + Name(id='tx_decoded', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v_addend', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='tx_decoded', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='BlobTransaction', + ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='signing_hash', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='t8n', ctx=Load()), + attr='fork', + ctx=Load()), + attr='signing_hash_4844', + ctx=Load()), + args=[ + Name(id='tx_decoded', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='v_addend', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]))], + orelse=[ + Raise( + exc=Call( + func=Name(id='FatalException', ctx=Load()), + args=[ + Constant(value='Unknown transaction type')], + keywords=[]))])])])]), + Assign( + targets=[ + Tuple( + elts=[ + Name(id='r', ctx=Store()), + Name(id='s', ctx=Store()), + Name(id='y', ctx=Store())], + ctx=Store())], + value=Call( + func=Name(id='secp256k1_sign', ctx=Load()), + args=[ + Name(id='signing_hash', ctx=Load()), + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='secret_key', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Subscript( + value=Name(id='json_tx', ctx=Load()), + slice=Constant(value='r'), + ctx=Store())], + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Name(id='r', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Subscript( + value=Name(id='json_tx', ctx=Load()), + slice=Constant(value='s'), + ctx=Store())], + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Name(id='s', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Subscript( + value=Name(id='json_tx', ctx=Load()), + slice=Constant(value='v'), + ctx=Store())], + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + BinOp( + left=Name(id='y', ctx=Load()), + op=Add(), + right=Name(id='v_addend', ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=Name(id='v_addend', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='json_tx', ctx=Load()), + slice=Constant(value='y_parity'), + ctx=Store())], + value=Subscript( + value=Name(id='json_tx', ctx=Load()), + slice=Constant(value='v'), + ctx=Load()))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='Result', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='Type that represents the result of a transition execution')), + AnnAssign( + target=Name(id='difficulty', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='base_fee', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='state_root', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + value=Constant(value=None), + simple=1), + AnnAssign( + target=Name(id='tx_root', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + value=Constant(value=None), + simple=1), + AnnAssign( + target=Name(id='receipt_root', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + value=Constant(value=None), + simple=1), + AnnAssign( + target=Name(id='withdrawals_root', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + value=Constant(value=None), + simple=1), + AnnAssign( + target=Name(id='logs_hash', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + value=Constant(value=None), + simple=1), + AnnAssign( + target=Name(id='bloom', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + value=Constant(value=None), + simple=1), + AnnAssign( + target=Name(id='receipts', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + value=Constant(value=None), + simple=1), + AnnAssign( + target=Name(id='rejected', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + value=Constant(value=None), + simple=1), + AnnAssign( + target=Name(id='gas_used', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + value=Constant(value=None), + simple=1), + AnnAssign( + target=Name(id='excess_blob_gas', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='U64', ctx=Load()), + ctx=Load()), + value=Constant(value=None), + simple=1), + AnnAssign( + target=Name(id='blob_gas_used', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + value=Constant(value=None), + simple=1), + FunctionDef( + name='to_json', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Encode the result to JSON')), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Dict(keys=[], values=[])), + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='stateRoot'), + ctx=Store())], + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='state_root', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[]))), + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='txRoot'), + ctx=Store())], + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='tx_root', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[]))), + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='receiptsRoot'), + ctx=Store())], + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='receipt_root', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[]))), + If( + test=Attribute( + value=Name(id='self', ctx=Load()), + attr='withdrawals_root', + ctx=Load()), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='withdrawalsRoot'), + ctx=Store())], + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='withdrawals_root', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[])))], + orelse=[]), + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='logsHash'), + ctx=Store())], + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='logs_hash', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[]))), + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='logsBloom'), + ctx=Store())], + value=BinOp( + left=Constant(value='0x'), + op=Add(), + right=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='bloom', + ctx=Load()), + attr='hex', + ctx=Load()), + args=[], + keywords=[]))), + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='gasUsed'), + ctx=Store())], + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='gas_used', + ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='self', ctx=Load()), + attr='difficulty', + ctx=Load()), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='currentDifficulty'), + ctx=Store())], + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='difficulty', + ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='currentDifficulty'), + ctx=Store())], + value=Constant(value=None))]), + If( + test=Attribute( + value=Name(id='self', ctx=Load()), + attr='base_fee', + ctx=Load()), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='currentBaseFee'), + ctx=Store())], + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='base_fee', + ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='currentBaseFee'), + ctx=Store())], + value=Constant(value=None))]), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='excess_blob_gas', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='currentExcessBlobGas'), + ctx=Store())], + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='excess_blob_gas', + ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='blob_gas_used', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='blobGasUsed'), + ctx=Store())], + value=Call( + func=Name(id='hex', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='blob_gas_used', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='rejected'), + ctx=Store())], + value=ListComp( + elt=Dict( + keys=[ + Constant(value='index'), + Constant(value='error')], + values=[ + Name(id='idx', ctx=Load()), + Name(id='error', ctx=Load())]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='idx', ctx=Store()), + Name(id='error', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='rejected', + ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])), + Assign( + targets=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='receipts'), + ctx=Store())], + value=ListComp( + elt=Dict( + keys=[ + Constant(value='transactionHash'), + Constant(value='gasUsed')], + values=[ + Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value='transactionHash'), + ctx=Load()), + Subscript( + value=Name(id='item', ctx=Load()), + slice=Constant(value='gasUsed'), + ctx=Load())]), + generators=[ + comprehension( + target=Name(id='item', ctx=Store()), + iter=Attribute( + value=Name(id='self', ctx=Load()), + attr='receipts', + ctx=Load()), + ifs=[], + is_async=0)])), + Return( + value=Name(id='data', ctx=Load()))], + decorator_list=[], + returns=Name(id='Any', ctx=Load()))], + decorator_list=[ + Name(id='dataclass', ctx=Load())])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/t8n/t8n_types.v b/coq/ethereum_spec_tools/evm_tools/t8n/t8n_types.v new file mode 100644 index 0000000000..0d749456ff --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/t8n/t8n_types.v @@ -0,0 +1,5 @@ +(* Generated *) +(* +Define the types used by the t8n tool. +*) + diff --git a/coq/ethereum_spec_tools/evm_tools/utils.ast b/coq/ethereum_spec_tools/evm_tools/utils.ast new file mode 100644 index 0000000000..346b86bfbf --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/utils.ast @@ -0,0 +1,934 @@ +Module( + body=[ + Expr( + value=Constant(value='\nUtilities for the EVM tools\n')), + Import( + names=[ + alias(name='json')]), + Import( + names=[ + alias(name='logging')]), + Import( + names=[ + alias(name='sys')]), + ImportFrom( + module='typing', + names=[ + alias(name='Any'), + alias(name='Callable'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='Tuple'), + alias(name='TypeVar')], + level=0), + Import( + names=[ + alias(name='coincurve')]), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum.crypto.hash', + names=[ + alias(name='Hash32')], + level=0), + ImportFrom( + module='ethereum_spec_tools.forks', + names=[ + alias(name='Hardfork')], + level=0), + Assign( + targets=[ + Name(id='W', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='W'), + Name(id='Uint', ctx=Load()), + Name(id='U64', ctx=Load()), + Name(id='U256', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='EXCEPTION_MAPS', ctx=Store())], + value=Dict( + keys=[ + Constant(value='FrontierToHomesteadAt5'), + Constant(value='HomesteadToDaoAt5'), + Constant(value='HomesteadToEIP150At5'), + Constant(value='EIP158ToByzantiumAt5'), + Constant(value='ByzantiumToConstantinopleAt5'), + Constant(value='ConstantinopleToIstanbulAt5'), + Constant(value='BerlinToLondonAt5'), + Constant(value='EIP150'), + Constant(value='EIP158'), + Constant(value='Merge'), + Constant(value='ConstantinopleFix')], + values=[ + Dict( + keys=[ + Constant(value='fork_blocks')], + values=[ + List( + elts=[ + Tuple( + elts=[ + Constant(value='frontier'), + Constant(value=0)], + ctx=Load()), + Tuple( + elts=[ + Constant(value='homestead'), + Constant(value=5)], + ctx=Load())], + ctx=Load())]), + Dict( + keys=[ + Constant(value='fork_blocks')], + values=[ + List( + elts=[ + Tuple( + elts=[ + Constant(value='homestead'), + Constant(value=0)], + ctx=Load()), + Tuple( + elts=[ + Constant(value='dao_fork'), + Constant(value=5)], + ctx=Load())], + ctx=Load())]), + Dict( + keys=[ + Constant(value='fork_blocks')], + values=[ + List( + elts=[ + Tuple( + elts=[ + Constant(value='homestead'), + Constant(value=0)], + ctx=Load()), + Tuple( + elts=[ + Constant(value='tangerine_whistle'), + Constant(value=5)], + ctx=Load())], + ctx=Load())]), + Dict( + keys=[ + Constant(value='fork_blocks')], + values=[ + List( + elts=[ + Tuple( + elts=[ + Constant(value='spurious_dragon'), + Constant(value=0)], + ctx=Load()), + Tuple( + elts=[ + Constant(value='byzantium'), + Constant(value=5)], + ctx=Load())], + ctx=Load())]), + Dict( + keys=[ + Constant(value='fork_blocks')], + values=[ + List( + elts=[ + Tuple( + elts=[ + Constant(value='byzantium'), + Constant(value=0)], + ctx=Load()), + Tuple( + elts=[ + Constant(value='constantinople'), + Constant(value=5)], + ctx=Load())], + ctx=Load())]), + Dict( + keys=[ + Constant(value='fork_blocks')], + values=[ + List( + elts=[ + Tuple( + elts=[ + Constant(value='constantinople'), + Constant(value=0)], + ctx=Load()), + Tuple( + elts=[ + Constant(value='istanbul'), + Constant(value=5)], + ctx=Load())], + ctx=Load())]), + Dict( + keys=[ + Constant(value='fork_blocks')], + values=[ + List( + elts=[ + Tuple( + elts=[ + Constant(value='berlin'), + Constant(value=0)], + ctx=Load()), + Tuple( + elts=[ + Constant(value='london'), + Constant(value=5)], + ctx=Load())], + ctx=Load())]), + Dict( + keys=[ + Constant(value='fork_blocks')], + values=[ + List( + elts=[ + Tuple( + elts=[ + Constant(value='tangerine_whistle'), + Constant(value=0)], + ctx=Load())], + ctx=Load())]), + Dict( + keys=[ + Constant(value='fork_blocks')], + values=[ + List( + elts=[ + Tuple( + elts=[ + Constant(value='spurious_dragon'), + Constant(value=0)], + ctx=Load())], + ctx=Load())]), + Dict( + keys=[ + Constant(value='fork_blocks')], + values=[ + List( + elts=[ + Tuple( + elts=[ + Constant(value='paris'), + Constant(value=0)], + ctx=Load())], + ctx=Load())]), + Dict( + keys=[ + Constant(value='fork_blocks')], + values=[ + List( + elts=[ + Tuple( + elts=[ + Constant(value='constantinople'), + Constant(value=0)], + ctx=Load())], + ctx=Load())])])), + Assign( + targets=[ + Name(id='UNSUPPORTED_FORKS', ctx=Store())], + value=Tuple( + elts=[ + Constant(value='constantinople')], + ctx=Load())), + FunctionDef( + name='parse_hex_or_int', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='value', + annotation=Name(id='str', ctx=Load())), + arg( + arg='to_type', + annotation=Subscript( + value=Name(id='Callable', ctx=Load()), + slice=Tuple( + elts=[ + List( + elts=[ + Name(id='int', ctx=Load())], + ctx=Load()), + Name(id='W', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Read a Uint type from a hex string or int')), + If( + test=BoolOp( + op=And(), + values=[ + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='value', ctx=Load()), + Name(id='str', ctx=Load())], + keywords=[]), + Call( + func=Attribute( + value=Name(id='value', ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Constant(value='0x')], + keywords=[])]), + body=[ + Return( + value=Call( + func=Name(id='to_type', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Subscript( + value=Name(id='value', ctx=Load()), + slice=Slice( + lower=Constant(value=2)), + ctx=Load()), + Constant(value=16)], + keywords=[])], + keywords=[]))], + orelse=[ + Return( + value=Call( + func=Name(id='to_type', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='value', ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[], + returns=Name(id='W', ctx=Load())), + ClassDef( + name='FatalException', + bases=[ + Name(id='Exception', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='Exception that causes the tool to stop')), + Pass()], + decorator_list=[]), + FunctionDef( + name='ensure_success', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='f', + annotation=Name(id='Callable', ctx=Load()))], + vararg=arg( + arg='args', + annotation=Name(id='Any', ctx=Load())), + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Ensure that the function call succeeds.\n Raise a FatalException if it fails.\n ')), + Try( + body=[ + Return( + value=Call( + func=Name(id='f', ctx=Load()), + args=[ + Starred( + value=Name(id='args', ctx=Load()), + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='Exception', ctx=Load()), + name='e', + body=[ + Raise( + exc=Call( + func=Name(id='FatalException', ctx=Load()), + args=[ + Name(id='e', ctx=Load())], + keywords=[]))])], + orelse=[], + finalbody=[])], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='get_module_name', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='forks', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='options', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='stdin', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the module name and the fork block for the given state fork.\n ')), + If( + test=Compare( + left=Call( + func=Attribute( + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='state_fork', + ctx=Load()), + attr='casefold', + ctx=Load()), + args=[], + keywords=[]), + ops=[ + In()], + comparators=[ + Name(id='UNSUPPORTED_FORKS', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='sys', ctx=Load()), + attr='exit', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Unsupported state fork: '), + FormattedValue( + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='state_fork', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + AnnAssign( + target=Name(id='exception_config', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='str', ctx=Load()), + Name(id='Any', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=Constant(value=None), + simple=1), + Try( + body=[ + Assign( + targets=[ + Name(id='exception_config', ctx=Store())], + value=Subscript( + value=Name(id='EXCEPTION_MAPS', ctx=Load()), + slice=Attribute( + value=Name(id='options', ctx=Load()), + attr='state_fork', + ctx=Load()), + ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='KeyError', ctx=Load()), + body=[ + Pass()])], + orelse=[], + finalbody=[]), + If( + test=Name(id='exception_config', ctx=Load()), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='input_env', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='stdin')]), + body=[ + Assert( + test=Compare( + left=Name(id='stdin', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Subscript( + value=Name(id='stdin', ctx=Load()), + slice=Constant(value='env'), + ctx=Load()))], + orelse=[ + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='open', ctx=Load()), + args=[ + Attribute( + value=Name(id='options', ctx=Load()), + attr='input_env', + ctx=Load()), + Constant(value='r')], + keywords=[]), + optional_vars=Name(id='f', ctx=Store()))], + body=[ + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='f', ctx=Load())], + keywords=[]))])]), + Assign( + targets=[ + Name(id='block_number', ctx=Store())], + value=Call( + func=Name(id='parse_hex_or_int', ctx=Load()), + args=[ + Subscript( + value=Name(id='data', ctx=Load()), + slice=Constant(value='currentNumber'), + ctx=Load()), + Name(id='Uint', ctx=Load())], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='fork', ctx=Store()), + Name(id='fork_block', ctx=Store())], + ctx=Store()), + iter=Subscript( + value=Name(id='exception_config', ctx=Load()), + slice=Constant(value='fork_blocks'), + ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='block_number', ctx=Load()), + ops=[ + GtE()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='fork_block', ctx=Load())], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='current_fork_module', ctx=Store())], + value=Name(id='fork', ctx=Load())), + Assign( + targets=[ + Name(id='current_fork_block', ctx=Store())], + value=Name(id='fork_block', ctx=Load()))], + orelse=[])], + orelse=[]), + Return( + value=Tuple( + elts=[ + Name(id='current_fork_module', ctx=Load()), + Name(id='current_fork_block', ctx=Load())], + ctx=Load()))], + orelse=[]), + For( + target=Name(id='fork', ctx=Store()), + iter=Name(id='forks', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='fork_module', ctx=Store())], + value=Subscript( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='fork', ctx=Load()), + attr='name', + ctx=Load()), + attr='split', + ctx=Load()), + args=[ + Constant(value='.')], + keywords=[]), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load())), + Assign( + targets=[ + Name(id='key', ctx=Store())], + value=Call( + func=Attribute( + value=Constant(value=''), + attr='join', + ctx=Load()), + args=[ + GeneratorExp( + elt=Call( + func=Attribute( + value=Name(id='x', ctx=Load()), + attr='title', + ctx=Load()), + args=[], + keywords=[]), + generators=[ + comprehension( + target=Name(id='x', ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='fork_module', ctx=Load()), + attr='split', + ctx=Load()), + args=[ + Constant(value='_')], + keywords=[]), + ifs=[], + is_async=0)])], + keywords=[])), + If( + test=Compare( + left=Name(id='key', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='options', ctx=Load()), + attr='state_fork', + ctx=Load())]), + body=[ + Return( + value=Tuple( + elts=[ + Name(id='fork_module', ctx=Load()), + Constant(value=0)], + ctx=Load()))], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='sys', ctx=Load()), + attr='exit', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Unsupported state fork: '), + FormattedValue( + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='state_fork', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='str', ctx=Load()), + Name(id='int', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='get_supported_forks', + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the supported forks.\n ')), + Assign( + targets=[ + Name(id='supported_forks', ctx=Store())], + value=ListComp( + elt=Call( + func=Attribute( + value=Attribute( + value=Name(id='fork', ctx=Load()), + attr='title_case_name', + ctx=Load()), + attr='replace', + ctx=Load()), + args=[ + Constant(value=' '), + Constant(value='')], + keywords=[]), + generators=[ + comprehension( + target=Name(id='fork', ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='Hardfork', ctx=Load()), + attr='discover', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])), + Expr( + value=Call( + func=Attribute( + value=Name(id='supported_forks', ctx=Load()), + attr='extend', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='EXCEPTION_MAPS', ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='supported_forks', ctx=Store())], + value=ListComp( + elt=Name(id='fork', ctx=Load()), + generators=[ + comprehension( + target=Name(id='fork', ctx=Store()), + iter=Name(id='supported_forks', ctx=Load()), + ifs=[ + Compare( + left=Call( + func=Attribute( + value=Name(id='fork', ctx=Load()), + attr='casefold', + ctx=Load()), + args=[], + keywords=[]), + ops=[ + NotIn()], + comparators=[ + Name(id='UNSUPPORTED_FORKS', ctx=Load())])], + is_async=0)])), + Return( + value=Name(id='supported_forks', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load())), + FunctionDef( + name='get_stream_logger', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='name', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get a logger that writes to stdout.\n ')), + Assign( + targets=[ + Name(id='logger', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='logging', ctx=Load()), + attr='getLogger', + ctx=Load()), + args=[ + Name(id='name', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='logger', ctx=Load()), + attr='handlers', + ctx=Load())), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='logger', ctx=Load()), + attr='setLevel', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='level', + value=Attribute( + value=Name(id='logging', ctx=Load()), + attr='INFO', + ctx=Load()))])), + Assign( + targets=[ + Name(id='stream_handler', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='logging', ctx=Load()), + attr='StreamHandler', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='formatter', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='logging', ctx=Load()), + attr='Formatter', + ctx=Load()), + args=[ + Constant(value='%(levelname)s:%(name)s:%(message)s')], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='stream_handler', ctx=Load()), + attr='setFormatter', + ctx=Load()), + args=[ + Name(id='formatter', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='logger', ctx=Load()), + attr='addHandler', + ctx=Load()), + args=[ + Name(id='stream_handler', ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='logger', ctx=Load()))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='secp256k1_sign', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='msg_hash', + annotation=Name(id='Hash32', ctx=Load())), + arg( + arg='secret_key', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns the signature of a message hash given the secret key.\n ')), + Assign( + targets=[ + Name(id='private_key', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='coincurve', ctx=Load()), + attr='PrivateKey', + ctx=Load()), + attr='from_int', + ctx=Load()), + args=[ + Name(id='secret_key', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='signature', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='private_key', ctx=Load()), + attr='sign_recoverable', + ctx=Load()), + args=[ + Name(id='msg_hash', ctx=Load())], + keywords=[ + keyword( + arg='hasher', + value=Constant(value=None))])), + Return( + value=Tuple( + elts=[ + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='signature', ctx=Load()), + slice=Slice( + lower=Constant(value=0), + upper=Constant(value=32)), + ctx=Load())], + keywords=[]), + Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Name(id='signature', ctx=Load()), + slice=Slice( + lower=Constant(value=32), + upper=Constant(value=64)), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Subscript( + value=Name(id='signature', ctx=Load()), + slice=Constant(value=64), + ctx=Load())], + keywords=[])], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='U256', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/evm_tools/utils.v b/coq/ethereum_spec_tools/evm_tools/utils.v new file mode 100644 index 0000000000..7c4d31a8cf --- /dev/null +++ b/coq/ethereum_spec_tools/evm_tools/utils.v @@ -0,0 +1,80 @@ +(* Generated *) +(* +Utilities for the EVM tools +*) + + +Definition parse_hex_or_int (value : str) (to_type : (* TODO type *)) : M W := + (*Read a Uint type from a hex string or int*) + (* TODO statement *) + M.pure tt. + +Definition ensure_success (f : Callable) : M Any := + (* + Ensure that the function call succeeds. + Raise a FatalException if it fails. + *) + (* TODO statement *) + M.pure tt. + +Definition get_module_name (forks : Any) (options : Any) (stdin : Any) : M (* TODO type *) := + (* + Get the module name and the fork block for the given state fork. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + do* [[ M.get_field ~(| M.get_local ~(| "sys" |), "exit" |) ~(| + (* TODO expression *) + |) ]] in + M.pure tt. + +Definition get_supported_forks : M (* TODO type *) := + (* + Get the supported forks. + *) + do* M.assign "supported_forks" [[ + (* TODO expression *) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "supported_forks" |), "extend" |) ~(| + M.get_field ~(| M.get_local ~(| "EXCEPTION_MAPS" |), "keys" |) ~(| + + |) + |) ]] in + do* M.assign "supported_forks" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + M.pure tt. + +Definition get_stream_logger (name : str) : M Any := + (* + Get a logger that writes to stdout. + *) + do* M.assign "logger" [[ + M.get_field ~(| M.get_local ~(| "logging" |), "getLogger" |) ~(| + name + |) in + ]] in + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition secp256k1_sign (msg_hash : Hash32) (secret_key : int) : M (* TODO type *) := + (* + Returns the signature of a message hash given the secret key. + *) + do* M.assign "private_key" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "coincurve" |), "PrivateKey" |), "from_int" |) ~(| + secret_key + |) in + ]] in + do* M.assign "signature" [[ + M.get_field ~(| M.get_local ~(| "private_key" |), "sign_recoverable" |) ~(| + msg_hash + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum_spec_tools/forks.ast b/coq/ethereum_spec_tools/forks.ast new file mode 100644 index 0000000000..13b7811581 --- /dev/null +++ b/coq/ethereum_spec_tools/forks.ast @@ -0,0 +1,1430 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Forks\n^^^^^^^^^^^^^^\n\nDetects Python packages that specify Ethereum hardforks.\n')), + Import( + names=[ + alias(name='importlib')]), + Import( + names=[ + alias(name='importlib.abc')]), + Import( + names=[ + alias(name='importlib.util')]), + Import( + names=[ + alias(name='pkgutil')]), + ImportFrom( + module='enum', + names=[ + alias(name='Enum'), + alias(name='auto')], + level=0), + ImportFrom( + module='pathlib', + names=[ + alias(name='PurePath')], + level=0), + ImportFrom( + module='pkgutil', + names=[ + alias(name='ModuleInfo')], + level=0), + ImportFrom( + module='types', + names=[ + alias(name='ModuleType')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='TYPE_CHECKING'), + alias(name='Any'), + alias(name='Dict'), + alias(name='Iterator'), + alias(name='List'), + alias(name='Optional'), + alias(name='Type'), + alias(name='TypeVar')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U256'), + alias(name='Uint')], + level=0), + If( + test=Name(id='TYPE_CHECKING', ctx=Load()), + body=[ + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ForkCriteria')], + level=0)], + orelse=[]), + ClassDef( + name='ConsensusType', + bases=[ + Name(id='Enum', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n How a fork chooses its canonical chain.\n ')), + Assign( + targets=[ + Name(id='PROOF_OF_WORK', ctx=Store())], + value=Call( + func=Name(id='auto', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='PROOF_OF_STAKE', ctx=Store())], + value=Call( + func=Name(id='auto', ctx=Load()), + args=[], + keywords=[])), + FunctionDef( + name='is_pow', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns True if self == PROOF_OF_WORK.\n ')), + Return( + value=Compare( + left=Name(id='self', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='ConsensusType', ctx=Load()), + attr='PROOF_OF_WORK', + ctx=Load())]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='is_pos', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Returns True if self == PROOF_OF_STAKE.\n ')), + Return( + value=Compare( + left=Name(id='self', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Name(id='ConsensusType', ctx=Load()), + attr='PROOF_OF_STAKE', + ctx=Load())]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load()))], + decorator_list=[]), + Assign( + targets=[ + Name(id='H', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='H')], + keywords=[ + keyword( + arg='bound', + value=Constant(value='Hardfork'))])), + ClassDef( + name='Hardfork', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Metadata associated with an Ethereum hardfork.\n ')), + AnnAssign( + target=Name(id='mod', ctx=Store()), + annotation=Name(id='ModuleType', ctx=Load()), + simple=1), + FunctionDef( + name='discover', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='H', ctx=Load()), + ctx=Load())), + arg( + arg='base', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='PurePath', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + Expr( + value=Constant(value='\n Find packages which contain Ethereum hardfork specifications.\n ')), + If( + test=Compare( + left=Name(id='base', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='ethereum', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='importlib', ctx=Load()), + attr='import_module', + ctx=Load()), + args=[ + Constant(value='ethereum')], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='spec', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='importlib', ctx=Load()), + attr='util', + ctx=Load()), + attr='spec_from_file_location', + ctx=Load()), + args=[ + Constant(value='ethereum'), + BinOp( + left=Name(id='base', ctx=Load()), + op=Div(), + right=Constant(value='__init__.py'))], + keywords=[ + keyword( + arg='submodule_search_locations', + value=List(elts=[], ctx=Load()))])), + If( + test=Compare( + left=Name(id='spec', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Raise( + exc=Call( + func=Name(id='ValueError', ctx=Load()), + args=[ + Constant(value='unable to find module from file')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='ethereum', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='importlib', ctx=Load()), + attr='util', + ctx=Load()), + attr='module_from_spec', + ctx=Load()), + args=[ + Name(id='spec', ctx=Load())], + keywords=[])), + If( + test=BoolOp( + op=And(), + values=[ + Attribute( + value=Name(id='spec', ctx=Load()), + attr='loader', + ctx=Load()), + Call( + func=Name(id='hasattr', ctx=Load()), + args=[ + Attribute( + value=Name(id='spec', ctx=Load()), + attr='loader', + ctx=Load()), + Constant(value='exec_module')], + keywords=[])]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='spec', ctx=Load()), + attr='loader', + ctx=Load()), + attr='exec_module', + ctx=Load()), + args=[ + Name(id='ethereum', ctx=Load())], + keywords=[]))], + orelse=[])]), + Assign( + targets=[ + Name(id='path', ctx=Store())], + value=Call( + func=Name(id='getattr', ctx=Load()), + args=[ + Name(id='ethereum', ctx=Load()), + Constant(value='__path__'), + Constant(value=None)], + keywords=[])), + If( + test=Compare( + left=Name(id='path', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Raise( + exc=Call( + func=Name(id='ValueError', ctx=Load()), + args=[ + Constant(value='module `ethereum` has no path information')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='modules', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='pkgutil', ctx=Load()), + attr='iter_modules', + ctx=Load()), + args=[ + Name(id='path', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='ethereum', ctx=Load()), + attr='__name__', + ctx=Load()), + op=Add(), + right=Constant(value='.'))], + keywords=[])), + Assign( + targets=[ + Name(id='modules', ctx=Store())], + value=GeneratorExp( + elt=Name(id='module', ctx=Load()), + generators=[ + comprehension( + target=Name(id='module', ctx=Store()), + iter=Name(id='modules', ctx=Load()), + ifs=[ + Attribute( + value=Name(id='module', ctx=Load()), + attr='ispkg', + ctx=Load())], + is_async=0)])), + AnnAssign( + target=Name(id='forks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='H', ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='pkg', ctx=Store()), + iter=Name(id='modules', ctx=Load()), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Attribute( + value=Name(id='pkg', ctx=Load()), + attr='module_finder', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='importlib', ctx=Load()), + attr='abc', + ctx=Load()), + attr='MetaPathFinder', + ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='found', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='pkg', ctx=Load()), + attr='module_finder', + ctx=Load()), + attr='find_spec', + ctx=Load()), + args=[ + Attribute( + value=Name(id='pkg', ctx=Load()), + attr='name', + ctx=Load()), + Constant(value=None)], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='found', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='pkg', ctx=Load()), + attr='module_finder', + ctx=Load()), + attr='find_spec', + ctx=Load()), + args=[ + Attribute( + value=Name(id='pkg', ctx=Load()), + attr='name', + ctx=Load())], + keywords=[]))]), + If( + test=UnaryOp( + op=Not(), + operand=Name(id='found', ctx=Load())), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='unable to find module spec for '), + FormattedValue( + value=Attribute( + value=Name(id='pkg', ctx=Load()), + attr='name', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='mod', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='importlib', ctx=Load()), + attr='util', + ctx=Load()), + attr='module_from_spec', + ctx=Load()), + args=[ + Name(id='found', ctx=Load())], + keywords=[])), + If( + test=Attribute( + value=Name(id='found', ctx=Load()), + attr='loader', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='found', ctx=Load()), + attr='loader', + ctx=Load()), + attr='exec_module', + ctx=Load()), + args=[ + Name(id='mod', ctx=Load())], + keywords=[]))], + orelse=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='No loader found for module '), + FormattedValue( + value=Attribute( + value=Name(id='pkg', ctx=Load()), + attr='name', + ctx=Load()), + conversion=-1)])], + keywords=[]))]), + If( + test=Call( + func=Name(id='hasattr', ctx=Load()), + args=[ + Name(id='mod', ctx=Load()), + Constant(value='FORK_CRITERIA')], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='forks', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Name(id='cls', ctx=Load()), + args=[ + Name(id='mod', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='forks', ctx=Load()), + attr='sort', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='key', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[ + arg(arg='fork')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Attribute( + value=Name(id='fork', ctx=Load()), + attr='criteria', + ctx=Load())))])), + Return( + value=Name(id='forks', ctx=Load()))], + decorator_list=[ + Name(id='classmethod', ctx=Load())], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='H', ctx=Load()), + ctx=Load())), + FunctionDef( + name='load', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='H', ctx=Load()), + ctx=Load())), + arg( + arg='config_dict', + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Constant(value='ForkCriteria'), + Name(id='str', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load the forks from a config dict specifying fork blocks and\n timestamps.\n ')), + Assign( + targets=[ + Name(id='config', ctx=Store())], + value=Call( + func=Name(id='sorted', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='config_dict', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[])], + keywords=[ + keyword( + arg='key', + value=Lambda( + args=arguments( + posonlyargs=[], + args=[ + arg(arg='x')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=Subscript( + value=Name(id='x', ctx=Load()), + slice=Constant(value=0), + ctx=Load())))])), + Assign( + targets=[ + Name(id='forks', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Tuple( + elts=[ + Name(id='criteria', ctx=Store()), + Name(id='name', ctx=Store())], + ctx=Store()), + iter=Name(id='config', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='mod', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='importlib', ctx=Load()), + attr='import_module', + ctx=Load()), + args=[ + BinOp( + left=Constant(value='ethereum.'), + op=Add(), + right=Name(id='name', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='mod', ctx=Load()), + attr='FORK_CRITERIA', + ctx=Store())], + value=Name(id='criteria', ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='forks', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Name(id='cls', ctx=Load()), + args=[ + Name(id='mod', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='forks', ctx=Load()))], + decorator_list=[ + Name(id='classmethod', ctx=Load())], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='H', ctx=Load()), + ctx=Load())), + FunctionDef( + name='load_from_json', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='cls', + annotation=Subscript( + value=Name(id='Type', ctx=Load()), + slice=Name(id='H', ctx=Load()), + ctx=Load())), + arg( + arg='json', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Load fork config from the json format used by Geth.\n\n Does not support some forks that only exist on Mainnet. Use\n `discover()` for Mainnet.\n ')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber'), + alias(name='ByTimestamp')], + level=0), + Assign( + targets=[ + Name(id='c', ctx=Store())], + value=Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='config'), + ctx=Load())), + Assign( + targets=[ + Name(id='config', ctx=Store())], + value=Dict( + keys=[ + Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Subscript( + value=Name(id='c', ctx=Load()), + slice=Constant(value='homesteadBlock'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Subscript( + value=Name(id='c', ctx=Load()), + slice=Constant(value='eip150Block'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Subscript( + value=Name(id='c', ctx=Load()), + slice=Constant(value='eip155Block'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Subscript( + value=Name(id='c', ctx=Load()), + slice=Constant(value='byzantiumBlock'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Subscript( + value=Name(id='c', ctx=Load()), + slice=Constant(value='constantinopleBlock'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Subscript( + value=Name(id='c', ctx=Load()), + slice=Constant(value='istanbulBlock'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Subscript( + value=Name(id='c', ctx=Load()), + slice=Constant(value='berlinBlock'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Subscript( + value=Name(id='c', ctx=Load()), + slice=Constant(value='londonBlock'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='ByBlockNumber', ctx=Load()), + args=[ + Subscript( + value=Name(id='c', ctx=Load()), + slice=Constant(value='mergeForkBlock'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='ByTimestamp', ctx=Load()), + args=[ + Subscript( + value=Name(id='c', ctx=Load()), + slice=Constant(value='shanghaiTime'), + ctx=Load())], + keywords=[])], + values=[ + Constant(value='frontier'), + Constant(value='homestead'), + Constant(value='tangerine_whistle'), + Constant(value='spurious_dragon'), + Constant(value='byzantium'), + Constant(value='constantinople'), + Constant(value='istanbul'), + Constant(value='berlin'), + Constant(value='london'), + Constant(value='paris'), + Constant(value='shanghai')])), + If( + test=Compare( + left=Constant(value='daoForkBlock'), + ops=[ + In()], + comparators=[ + Name(id='c', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value='Hardfork.load_from_json() does not support Mainnet')], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='cls', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='config', ctx=Load())], + keywords=[]))], + decorator_list=[ + Name(id='classmethod', ctx=Load())], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='H', ctx=Load()), + ctx=Load())), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='mod', + annotation=Name(id='ModuleType', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='mod', + ctx=Store())], + value=Name(id='mod', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='consensus', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n How this fork chooses its canonical chain.\n ')), + If( + test=Call( + func=Name(id='hasattr', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + Constant(value='validate_proof_of_work')], + keywords=[]), + body=[ + Return( + value=Attribute( + value=Name(id='ConsensusType', ctx=Load()), + attr='PROOF_OF_WORK', + ctx=Load()))], + orelse=[ + Return( + value=Attribute( + value=Name(id='ConsensusType', ctx=Load()), + attr='PROOF_OF_STAKE', + ctx=Load()))])], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='ConsensusType', ctx=Load())), + FunctionDef( + name='criteria', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Criteria to trigger this hardfork.\n ')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ForkCriteria')], + level=0), + Assign( + targets=[ + Name(id='criteria', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='mod', + ctx=Load()), + attr='FORK_CRITERIA', + ctx=Load())), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='criteria', ctx=Load()), + Name(id='ForkCriteria', ctx=Load())], + keywords=[])), + Return( + value=Name(id='criteria', ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Constant(value='ForkCriteria')), + FunctionDef( + name='block', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Block number of the first block in this hard fork.\n ')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByBlockNumber')], + level=0), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='criteria', + ctx=Load()), + Name(id='ByBlockNumber', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='criteria', + ctx=Load()), + attr='block_number', + ctx=Load()))], + orelse=[ + Raise( + exc=Name(id='AttributeError', ctx=Load()))])], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Uint', ctx=Load())), + FunctionDef( + name='timestamp', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Block number of the first block in this hard fork.\n ')), + ImportFrom( + module='ethereum.fork_criteria', + names=[ + alias(name='ByTimestamp')], + level=0), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='criteria', + ctx=Load()), + Name(id='ByTimestamp', ctx=Load())], + keywords=[]), + body=[ + Return( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='criteria', + ctx=Load()), + attr='timestamp', + ctx=Load()))], + orelse=[ + Raise( + exc=Name(id='AttributeError', ctx=Load()))])], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='U256', ctx=Load())), + FunctionDef( + name='has_activated', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='timestamp', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check whether this fork has activated.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='criteria', + ctx=Load()), + attr='check', + ctx=Load()), + args=[ + Name(id='block_number', ctx=Load()), + Name(id='timestamp', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='path', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Path to the module containing this hard fork.\n ')), + Assign( + targets=[ + Name(id='got', ctx=Store())], + value=Call( + func=Name(id='getattr', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='mod', + ctx=Load()), + Constant(value='__path__'), + Constant(value=None)], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='got', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='got', ctx=Load()), + Name(id='str', ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Name(id='got', ctx=Load()))], + orelse=[]), + Try( + body=[ + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='got', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + Name(id='str', ctx=Load())], + keywords=[])), + Return( + value=Subscript( + value=Name(id='got', ctx=Load()), + slice=Constant(value=0), + ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='IndexError', ctx=Load()), + body=[ + Return( + value=Constant(value=None))])], + orelse=[], + finalbody=[])], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load())), + FunctionDef( + name='short_name', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Short name (without the `ethereum.` prefix) of the hard fork.\n ')), + Return( + value=Subscript( + value=Call( + func=Attribute( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='mod', + ctx=Load()), + attr='__name__', + ctx=Load()), + attr='split', + ctx=Load()), + args=[ + Constant(value='.')], + keywords=[]), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='str', ctx=Load())), + FunctionDef( + name='name', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Name of the hard fork.\n ')), + Return( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='mod', + ctx=Load()), + attr='__name__', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='str', ctx=Load())), + FunctionDef( + name='title_case_name', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Name of the hard fork.\n ')), + Return( + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='short_name', + ctx=Load()), + attr='replace', + ctx=Load()), + args=[ + Constant(value='_'), + Constant(value=' ')], + keywords=[]), + attr='title', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='str', ctx=Load())), + FunctionDef( + name='__repr__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Return repr(self).\n ')), + Return( + value=BinOp( + left=BinOp( + left=BinOp( + left=BinOp( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='__class__', + ctx=Load()), + attr='__name__', + ctx=Load()), + op=Add(), + right=Constant(value='(')), + op=Add(), + right=JoinedStr( + values=[ + Constant(value='name='), + FormattedValue( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='name', + ctx=Load()), + conversion=114), + Constant(value=', ')])), + op=Add(), + right=JoinedStr( + values=[ + Constant(value='criteria='), + FormattedValue( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='criteria', + ctx=Load()), + conversion=-1), + Constant(value=', ')])), + op=Add(), + right=Constant(value='...')), + op=Add(), + right=Constant(value=')')))], + decorator_list=[], + returns=Name(id='str', ctx=Load())), + FunctionDef( + name='import_module', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Return the module containing this specification.\n ')), + Return( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='mod', + ctx=Load()))], + decorator_list=[], + returns=Name(id='ModuleType', ctx=Load())), + FunctionDef( + name='module', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='name', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Import if necessary, and return the given module belonging to this hard\n fork.\n ')), + Return( + value=Call( + func=Attribute( + value=Name(id='importlib', ctx=Load()), + attr='import_module', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='mod', + ctx=Load()), + attr='__name__', + ctx=Load()), + op=Add(), + right=Constant(value='.')), + op=Add(), + right=Name(id='name', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='iter_modules', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Iterate through the (sub-)modules describing this hardfork.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='path', + ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Raise( + exc=Call( + func=Name(id='ValueError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='cannot walk '), + FormattedValue( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='name', + ctx=Load()), + conversion=-1), + Constant(value=', path is None')])], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='pkgutil', ctx=Load()), + attr='iter_modules', + ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='path', + ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='name', + ctx=Load()), + op=Add(), + right=Constant(value='.'))], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Iterator', ctx=Load()), + slice=Name(id='ModuleInfo', ctx=Load()), + ctx=Load())), + FunctionDef( + name='walk_packages', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Iterate recursively through the (sub-)modules describing this hardfork.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='path', + ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Raise( + exc=Call( + func=Name(id='ValueError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='cannot walk '), + FormattedValue( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='name', + ctx=Load()), + conversion=-1), + Constant(value=', path is None')])], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Name(id='pkgutil', ctx=Load()), + attr='walk_packages', + ctx=Load()), + args=[ + List( + elts=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='path', + ctx=Load())], + ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='name', + ctx=Load()), + op=Add(), + right=Constant(value='.'))], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Iterator', ctx=Load()), + slice=Name(id='ModuleInfo', ctx=Load()), + ctx=Load()))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/forks.v b/coq/ethereum_spec_tools/forks.v new file mode 100644 index 0000000000..9f0afb90d3 --- /dev/null +++ b/coq/ethereum_spec_tools/forks.v @@ -0,0 +1,8 @@ +(* Generated *) +(* +Ethereum Forks +^^^^^^^^^^^^^^ + +Detects Python packages that specify Ethereum hardforks. +*) + diff --git a/coq/ethereum_spec_tools/lint/__init__.ast b/coq/ethereum_spec_tools/lint/__init__.ast new file mode 100644 index 0000000000..62d912080e --- /dev/null +++ b/coq/ethereum_spec_tools/lint/__init__.ast @@ -0,0 +1,870 @@ +Module( + body=[ + Expr( + value=Constant(value='\nLints\n^^^^^\n\nChecks specific to the Ethereum specification source code.\n')), + Import( + names=[ + alias(name='ast')]), + Import( + names=[ + alias(name='importlib')]), + Import( + names=[ + alias(name='inspect')]), + Import( + names=[ + alias(name='pkgutil')]), + ImportFrom( + module='abc', + names=[ + alias(name='ABCMeta'), + alias(name='abstractmethod')], + level=0), + ImportFrom( + module='dataclasses', + names=[ + alias(name='dataclass')], + level=0), + ImportFrom( + module='itertools', + names=[ + alias(name='zip_longest')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Generator'), + alias(name='List'), + alias(name='Optional'), + alias(name='Sequence'), + alias(name='Tuple')], + level=0), + ImportFrom( + module='forks', + names=[ + alias(name='Hardfork')], + level=2), + FunctionDef( + name='compare_ast', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='old', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='AST', + ctx=Load())), + arg( + arg='new', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='AST', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Check if two nodes are the equal.\n ')), + If( + test=Compare( + left=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='old', ctx=Load())], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='new', ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=False))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='old', ctx=Load()), + Attribute( + value=Name(id='ast', ctx=Load()), + attr='Expr', + ctx=Load())], + keywords=[]), + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Attribute( + value=Name(id='old', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='ast', ctx=Load()), + attr='Constant', + ctx=Load())], + keywords=[]), + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='old', ctx=Load()), + attr='value', + ctx=Load()), + attr='value', + ctx=Load()), + Name(id='str', ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Constant(value=True))], + orelse=[]), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='old', ctx=Load()), + Attribute( + value=Name(id='ast', ctx=Load()), + attr='AST', + ctx=Load())], + keywords=[]), + body=[ + For( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='v', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Call( + func=Name(id='vars', ctx=Load()), + args=[ + Name(id='old', ctx=Load())], + keywords=[]), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Compare( + left=Name(id='k', ctx=Load()), + ops=[ + In()], + comparators=[ + Set( + elts=[ + Constant(value='lineno'), + Constant(value='end_lineno'), + Constant(value='col_offset'), + Constant(value='end_col_offset'), + Constant(value='ctx')])]), + body=[ + Continue()], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='compare_ast', ctx=Load()), + args=[ + Name(id='v', ctx=Load()), + Call( + func=Name(id='getattr', ctx=Load()), + args=[ + Name(id='new', ctx=Load()), + Name(id='k', ctx=Load())], + keywords=[])], + keywords=[])), + body=[ + Return( + value=Constant(value=False))], + orelse=[])], + orelse=[]), + Return( + value=Constant(value=True))], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='old', ctx=Load()), + Name(id='list', ctx=Load())], + keywords=[]), + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='new', ctx=Load()), + Name(id='list', ctx=Load())], + keywords=[])]), + body=[ + Return( + value=Call( + func=Name(id='all', ctx=Load()), + args=[ + GeneratorExp( + elt=Call( + func=Name(id='compare_ast', ctx=Load()), + args=[ + Name(id='old_item', ctx=Load()), + Name(id='new_item', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='old_item', ctx=Store()), + Name(id='new_item', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='zip_longest', ctx=Load()), + args=[ + Name(id='old', ctx=Load()), + Name(id='new', ctx=Load())], + keywords=[]), + ifs=[], + is_async=0)])], + keywords=[]))], + orelse=[ + Return( + value=Compare( + left=Name(id='old', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='new', ctx=Load())]))])])], + decorator_list=[], + returns=Name(id='bool', ctx=Load())), + FunctionDef( + name='walk_sources', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='fork', + annotation=Name(id='Hardfork', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Import the modules specifying a hardfork, and retrieve their source code.\n ')), + For( + target=Name(id='mod_info', ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='fork', ctx=Load()), + attr='walk_packages', + ctx=Load()), + args=[], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='mod', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='importlib', ctx=Load()), + attr='import_module', + ctx=Load()), + args=[ + Attribute( + value=Name(id='mod_info', ctx=Load()), + attr='name', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='source', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='inspect', ctx=Load()), + attr='getsource', + ctx=Load()), + args=[ + Name(id='mod', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='name', ctx=Store())], + value=Attribute( + value=Name(id='mod', ctx=Load()), + attr='__name__', + ctx=Load())), + If( + test=Call( + func=Attribute( + value=Name(id='name', ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Attribute( + value=Name(id='fork', ctx=Load()), + attr='name', + ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='name', ctx=Store())], + value=Subscript( + value=Name(id='name', ctx=Load()), + slice=Slice( + lower=Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Name(id='fork', ctx=Load()), + attr='name', + ctx=Load())], + keywords=[])), + ctx=Load()))], + orelse=[]), + Expr( + value=Yield( + value=Tuple( + elts=[ + Name(id='name', ctx=Load()), + Name(id='source', ctx=Load())], + ctx=Load())))], + orelse=[])], + decorator_list=[], + returns=Subscript( + value=Name(id='Generator', ctx=Load()), + slice=Tuple( + elts=[ + Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='str', ctx=Load()), + Name(id='str', ctx=Load())], + ctx=Load()), + ctx=Load()), + Constant(value=None), + Constant(value=None)], + ctx=Load()), + ctx=Load())), + ClassDef( + name='Diagnostic', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A diagnostic message generated while checking the specifications.\n ')), + AnnAssign( + target=Name(id='message', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1)], + decorator_list=[ + Name(id='dataclass', ctx=Load())]), + ClassDef( + name='Lint', + bases=[], + keywords=[ + keyword( + arg='metaclass', + value=Name(id='ABCMeta', ctx=Load()))], + body=[ + Expr( + value=Constant(value='\n A single check which may be performed against the specifications.\n ')), + FunctionDef( + name='lint', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='forks', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hardfork', ctx=Load()), + ctx=Load())), + arg( + arg='position', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Runs the check against the given forks, at the given position.\n\n Parameters\n ----------\n forks :\n All known hardforks.\n position :\n The particular hardfork to lint.\n '))], + decorator_list=[ + Name(id='abstractmethod', ctx=Load())], + returns=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load())), + FunctionDef( + name='_parse', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='source', + annotation=Name(id='str', ctx=Load())), + arg( + arg='visitor', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='NodeVisitor', + ctx=Load())), + arg( + arg='attr', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Walks the source string and extracts a sequence of identifiers.\n ')), + Assign( + targets=[ + Name(id='parsed', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='ast', ctx=Load()), + attr='parse', + ctx=Load()), + args=[ + Name(id='source', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='visitor', ctx=Load()), + attr='visit', + ctx=Load()), + args=[ + Name(id='parsed', ctx=Load())], + keywords=[])), + Return( + value=Call( + func=Name(id='getattr', ctx=Load()), + args=[ + Name(id='visitor', ctx=Load()), + Name(id='attr', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()))], + decorator_list=[]), + ClassDef( + name='Linter', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Checks the specification for style guideline violations.\n ')), + AnnAssign( + target=Name(id='lints', ctx=Store()), + annotation=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Lint', ctx=Load()), + ctx=Load()), + simple=1), + FunctionDef( + name='discover_lints', + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Discover subclasses of Lint.\n ')), + ImportFrom( + names=[ + alias(name='lints')], + level=1), + Assign( + targets=[ + Name(id='path', ctx=Store())], + value=Call( + func=Name(id='getattr', ctx=Load()), + args=[ + Name(id='lints', ctx=Load()), + Constant(value='__path__'), + Constant(value=None)], + keywords=[])), + If( + test=Compare( + left=Name(id='path', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='modules', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='pkgutil', ctx=Load()), + attr='iter_modules', + ctx=Load()), + args=[ + Name(id='path', ctx=Load()), + BinOp( + left=Attribute( + value=Name(id='lints', ctx=Load()), + attr='__name__', + ctx=Load()), + op=Add(), + right=Constant(value='.'))], + keywords=[])), + For( + target=Tuple( + elts=[ + Name(id='_', ctx=Store()), + Name(id='name', ctx=Store()), + Name(id='_', ctx=Store())], + ctx=Store()), + iter=Name(id='modules', ctx=Load()), + body=[ + Try( + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='importlib', ctx=Load()), + attr='import_module', + ctx=Load()), + args=[ + Name(id='name', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='Exception', ctx=Load()), + body=[ + Continue()])], + orelse=[], + finalbody=[])], + orelse=[]), + Assign( + targets=[ + Name(id='found', ctx=Store())], + value=Call( + func=Name(id='set', ctx=Load()), + args=[], + keywords=[])), + For( + target=Name(id='subclass', ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='Lint', ctx=Load()), + attr='__subclasses__', + ctx=Load()), + args=[], + keywords=[]), + body=[ + If( + test=Call( + func=Attribute( + value=Name(id='inspect', ctx=Load()), + attr='isabstract', + ctx=Load()), + args=[ + Name(id='subclass', ctx=Load())], + keywords=[]), + body=[ + Continue()], + orelse=[]), + Try( + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='found', ctx=Load()), + attr='add', + ctx=Load()), + args=[ + Call( + func=Name(id='subclass', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='Exception', ctx=Load()), + body=[ + Pass()])], + orelse=[], + finalbody=[])], + orelse=[]), + Return( + value=Call( + func=Name(id='list', ctx=Load()), + args=[ + Name(id='found', ctx=Load())], + keywords=[]))], + decorator_list=[ + Name(id='staticmethod', ctx=Load())], + returns=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Lint', ctx=Load()), + ctx=Load())), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='lints', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Lint', ctx=Load()), + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[ + Constant(value=None)]), + body=[ + If( + test=Compare( + left=Name(id='lints', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='lints', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Linter', ctx=Load()), + attr='discover_lints', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Name(id='lints', ctx=Load())), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value='no lints specified')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='lints', + ctx=Store())], + value=Name(id='lints', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='run', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Runs all enabled lints.\n ')), + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Constant(value=0)), + Assign( + targets=[ + Name(id='hardforks', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Hardfork', ctx=Load()), + attr='discover', + ctx=Load()), + args=[], + keywords=[])), + For( + target=Name(id='lint', ctx=Store()), + iter=Attribute( + value=Name(id='self', ctx=Load()), + attr='lints', + ctx=Load()), + body=[ + AnnAssign( + target=Name(id='diagnostics', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Name(id='hardfork', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Constant(value=0), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='hardforks', ctx=Load())], + keywords=[])], + keywords=[]), + body=[ + AugAssign( + target=Name(id='diagnostics', ctx=Store()), + op=Add(), + value=Call( + func=Attribute( + value=Name(id='lint', ctx=Load()), + attr='lint', + ctx=Load()), + args=[ + Name(id='hardforks', ctx=Load()), + Name(id='hardfork', ctx=Load())], + keywords=[])), + If( + test=Name(id='diagnostics', ctx=Load()), + body=[ + AugAssign( + target=Name(id='count', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='diagnostics', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='print', ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Subscript( + value=Name(id='hardforks', ctx=Load()), + slice=Name(id='hardfork', ctx=Load()), + ctx=Load()), + attr='name', + ctx=Load()), + conversion=-1), + Constant(value=' - '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='lint', ctx=Load()), + attr='__class__', + ctx=Load()), + attr='__name__', + ctx=Load()), + conversion=-1), + Constant(value=':')])], + keywords=[])), + For( + target=Name(id='diagnostic', ctx=Store()), + iter=Name(id='diagnostics', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='print', ctx=Load()), + args=[ + Constant(value='\t'), + Attribute( + value=Name(id='diagnostic', ctx=Load()), + attr='message', + ctx=Load())], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='diagnostics', ctx=Store())], + value=List(elts=[], ctx=Load()))], + orelse=[])], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='count', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Name(id='print', ctx=Load()), + args=[ + Constant(value='Total diagnostics:'), + Name(id='count', ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=IfExp( + test=Compare( + left=Name(id='count', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=Constant(value=1), + orelse=Constant(value=0)))], + decorator_list=[], + returns=Name(id='int', ctx=Load()))], + decorator_list=[]), + FunctionDef( + name='main', + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n `ethereum-spec-lint` checks for style and formatting issues specific to the\n Ethereum specification.\n ')), + Assign( + targets=[ + Name(id='linter', ctx=Store())], + value=Call( + func=Name(id='Linter', ctx=Load()), + args=[], + keywords=[])), + Return( + value=Call( + func=Attribute( + value=Name(id='linter', ctx=Load()), + attr='run', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Name(id='int', ctx=Load()))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/lint/__init__.v b/coq/ethereum_spec_tools/lint/__init__.v new file mode 100644 index 0000000000..463a1687db --- /dev/null +++ b/coq/ethereum_spec_tools/lint/__init__.v @@ -0,0 +1,37 @@ +(* Generated *) +(* +Lints +^^^^^ + +Checks specific to the Ethereum specification source code. +*) + + +Definition compare_ast (old : (* TODO type *)) (new : (* TODO type *)) : M bool := + (* + Check if two nodes are the equal. + *) + (* TODO statement *) + (* TODO statement *) + (* TODO statement *) + M.pure tt. + +Definition walk_sources (fork : Hardfork) : M (* TODO type *) := + (* + Import the modules specifying a hardfork, and retrieve their source code. + *) + (* TODO statement *) + M.pure tt. + +Definition main : M int := + (* + `ethereum-spec-lint` checks for style and formatting issues specific to the + Ethereum specification. + *) + do* M.assign "linter" [[ + M.get_local ~(| "Linter" |) ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum_spec_tools/lint/__main__.ast b/coq/ethereum_spec_tools/lint/__main__.ast new file mode 100644 index 0000000000..125b5eecc7 --- /dev/null +++ b/coq/ethereum_spec_tools/lint/__main__.ast @@ -0,0 +1,24 @@ +Module( + body=[ + Expr( + value=Constant(value='\nLinter Entry Point\n^^^^^^^^^^^^^^^^^^\n\nMain entry point for the ethereum spec lint tool.\n')), + Import( + names=[ + alias(name='sys')]), + ImportFrom( + names=[ + alias(name='main')], + level=1), + Expr( + value=Call( + func=Attribute( + value=Name(id='sys', ctx=Load()), + attr='exit', + ctx=Load()), + args=[ + Call( + func=Name(id='main', ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/lint/__main__.v b/coq/ethereum_spec_tools/lint/__main__.v new file mode 100644 index 0000000000..57d4ab0ee2 --- /dev/null +++ b/coq/ethereum_spec_tools/lint/__main__.v @@ -0,0 +1,8 @@ +(* Generated *) +(* +Linter Entry Point +^^^^^^^^^^^^^^^^^^ + +Main entry point for the ethereum spec lint tool. +*) + diff --git a/coq/ethereum_spec_tools/lint/lints/glacier_forks_hygiene.ast b/coq/ethereum_spec_tools/lint/lints/glacier_forks_hygiene.ast new file mode 100644 index 0000000000..bf5c3fa8fb --- /dev/null +++ b/coq/ethereum_spec_tools/lint/lints/glacier_forks_hygiene.ast @@ -0,0 +1,1253 @@ +Module( + body=[ + Expr( + value=Constant(value='\nGlacier Fork Hygiene Lint\n^^^^^^^^^^^^^^^^^^^^^^^^^\nEnsures that the glacier forks have changes only in BOMB_DELAY_BLOCKS.\n')), + Import( + names=[ + alias(name='ast')]), + Import( + names=[ + alias(name='sys')]), + ImportFrom( + module='typing', + names=[ + alias(name='Dict'), + alias(name='List'), + alias(name='Sequence')], + level=0), + ImportFrom( + module='ethereum_spec_tools.forks', + names=[ + alias(name='Hardfork')], + level=0), + ImportFrom( + module='ethereum_spec_tools.lint', + names=[ + alias(name='Diagnostic'), + alias(name='Lint'), + alias(name='compare_ast'), + alias(name='walk_sources')], + level=0), + Assign( + targets=[ + Name(id='EXCEPTIONAL_FILES', ctx=Store())], + value=List( + elts=[ + Tuple( + elts=[ + Constant(value='dao_fork'), + Constant(value='.dao')], + ctx=Load())], + ctx=Load())), + Assign( + targets=[ + Name(id='EXCEPTIONAL_DIFFS', ctx=Store())], + value=List( + elts=[ + Tuple( + elts=[ + Constant(value='dao_fork'), + Constant(value='.fork'), + Constant(value='apply_fork')], + ctx=Load()), + Tuple( + elts=[ + Constant(value='dao_fork'), + Constant(value='.fork'), + Constant(value='validate_header')], + ctx=Load()), + Tuple( + elts=[ + Constant(value='arrow_glacier'), + Constant(value='.fork'), + Constant(value='calculate_base_fee_per_gas')], + ctx=Load()), + Tuple( + elts=[ + Constant(value='arrow_glacier'), + Constant(value='.fork'), + Constant(value='validate_header')], + ctx=Load()), + Tuple( + elts=[ + Constant(value='arrow_glacier'), + Constant(value='.fork'), + Constant(value='INITIAL_BASE_FEE')], + ctx=Load())], + ctx=Load())), + FunctionDef( + name='add_diagnostic', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='diagnostics', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load())), + arg( + arg='message', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Adds a new diagnostic message.\n ')), + Assign( + targets=[ + Name(id='diagnostic', ctx=Store())], + value=Call( + func=Name(id='Diagnostic', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='message', + value=Name(id='message', ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='diagnostics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='diagnostic', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + ClassDef( + name='GlacierForksHygiene', + bases=[ + Name(id='Lint', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Ensures that the glacier forks have changes only in BOMB_DELAY_BLOCKS.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='delay_blocks', + ctx=Store())], + value=Dict( + keys=[ + Constant(value='muir_glacier'), + Constant(value='arrow_glacier'), + Constant(value='gray_glacier')], + values=[ + Constant(value=9000000), + Constant(value=10700000), + Constant(value=11400000)]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='lint', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='forks', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hardfork', ctx=Load()), + ctx=Load())), + arg( + arg='position', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Walks the sources for each hardfork and emits Diagnostic messages.\n ')), + Assign( + targets=[ + Name(id='fork_name', ctx=Store())], + value=Attribute( + value=Subscript( + value=Name(id='forks', ctx=Load()), + slice=Name(id='position', ctx=Load()), + ctx=Load()), + attr='short_name', + ctx=Load())), + If( + test=Compare( + left=Name(id='position', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Name(id='fork_name', ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Constant(value='dao_fork')]), + UnaryOp( + op=Not(), + operand=Call( + func=Attribute( + value=Name(id='fork_name', ctx=Load()), + attr='endswith', + ctx=Load()), + args=[ + Constant(value='_glacier')], + keywords=[]))]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='diagnostics', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='all_previous', ctx=Store())], + value=Call( + func=Name(id='dict', ctx=Load()), + args=[ + Call( + func=Name(id='walk_sources', ctx=Load()), + args=[ + Subscript( + value=Name(id='forks', ctx=Load()), + slice=BinOp( + left=Name(id='position', ctx=Load()), + op=Sub(), + right=Constant(value=1)), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='all_current', ctx=Store())], + value=Call( + func=Name(id='dict', ctx=Load()), + args=[ + Call( + func=Name(id='walk_sources', ctx=Load()), + args=[ + Subscript( + value=Name(id='forks', ctx=Load()), + slice=Name(id='position', ctx=Load()), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='all_files', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='set', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='all_previous', ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + op=BitOr(), + right=Call( + func=Name(id='set', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='all_current', ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]))), + For( + target=Name(id='file', ctx=Store()), + iter=Name(id='all_files', ctx=Load()), + body=[ + If( + test=Compare( + left=Tuple( + elts=[ + Name(id='fork_name', ctx=Load()), + Name(id='file', ctx=Load())], + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='EXCEPTIONAL_FILES', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + If( + test=Compare( + left=Name(id='file', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='all_previous', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='add_diagnostic', ctx=Load()), + args=[ + Name(id='diagnostics', ctx=Load()), + JoinedStr( + values=[ + Constant(value='the file `'), + FormattedValue( + value=Name(id='file', ctx=Load()), + conversion=-1), + Constant(value='` is added to `'), + FormattedValue( + value=Name(id='fork_name', ctx=Load()), + conversion=-1), + Constant(value='`. Glacier forks may only differ in difficulty block.')])], + keywords=[])), + Continue()], + orelse=[]), + If( + test=Compare( + left=Name(id='file', ctx=Load()), + ops=[ + NotIn()], + comparators=[ + Name(id='all_current', ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='add_diagnostic', ctx=Load()), + args=[ + Name(id='diagnostics', ctx=Load()), + JoinedStr( + values=[ + Constant(value='the file `'), + FormattedValue( + value=Name(id='file', ctx=Load()), + conversion=-1), + Constant(value='` is deleted from `'), + FormattedValue( + value=Name(id='fork_name', ctx=Load()), + conversion=-1), + Constant(value='`. Glacier forks may only differ in difficulty block.')])], + keywords=[])), + Continue()], + orelse=[]), + Assign( + targets=[ + Name(id='current_node', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_parse', + ctx=Load()), + args=[ + Subscript( + value=Name(id='all_current', ctx=Load()), + slice=Name(id='file', ctx=Load()), + ctx=Load()), + Call( + func=Name(id='_Visitor', ctx=Load()), + args=[], + keywords=[]), + Constant(value='items')], + keywords=[])), + Assign( + targets=[ + Name(id='previous_node', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_parse', + ctx=Load()), + args=[ + Subscript( + value=Name(id='all_previous', ctx=Load()), + slice=Name(id='file', ctx=Load()), + ctx=Load()), + Call( + func=Name(id='_Visitor', ctx=Load()), + args=[], + keywords=[]), + Constant(value='items')], + keywords=[])), + AugAssign( + target=Name(id='diagnostics', ctx=Store()), + op=Add(), + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='compare', + ctx=Load()), + args=[ + Name(id='fork_name', ctx=Load()), + Name(id='file', ctx=Load()), + Name(id='current_node', ctx=Load()), + Name(id='previous_node', ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='diagnostics', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load())), + FunctionDef( + name='compare', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='fork_name', + annotation=Name(id='str', ctx=Load())), + arg( + arg='name', + annotation=Name(id='str', ctx=Load())), + arg( + arg='current', + annotation=Name(id='Dict', ctx=Load())), + arg( + arg='previous', + annotation=Name(id='Dict', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compare nodes from two different modules for changes and\n emit diagnostics.\n ')), + AnnAssign( + target=Name(id='diagnostics', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='all_items', ctx=Store())], + value=BinOp( + left=Call( + func=Name(id='set', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='previous', ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + op=BitOr(), + right=Call( + func=Name(id='set', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='current', ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]))), + For( + target=Name(id='item', ctx=Store()), + iter=Name(id='all_items', ctx=Load()), + body=[ + If( + test=Compare( + left=Tuple( + elts=[ + Name(id='fork_name', ctx=Load()), + Name(id='name', ctx=Load()), + Name(id='item', ctx=Load())], + ctx=Load()), + ops=[ + In()], + comparators=[ + Name(id='EXCEPTIONAL_DIFFS', ctx=Load())]), + body=[ + Continue()], + orelse=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='previous_item', ctx=Store())], + value=Subscript( + value=Name(id='previous', ctx=Load()), + slice=Name(id='item', ctx=Load()), + ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='KeyError', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_diagnostic', ctx=Load()), + args=[ + Name(id='diagnostics', ctx=Load()), + JoinedStr( + values=[ + FormattedValue( + value=Name(id='item', ctx=Load()), + conversion=-1), + Constant(value=' in '), + FormattedValue( + value=Name(id='name', ctx=Load()), + conversion=-1), + Constant(value=' has been added. Glacier forks may only differ in difficulty block.')])], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + Try( + body=[ + Assign( + targets=[ + Name(id='current_item', ctx=Store())], + value=Subscript( + value=Name(id='current', ctx=Load()), + slice=Name(id='item', ctx=Load()), + ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='KeyError', ctx=Load()), + body=[ + Expr( + value=Call( + func=Name(id='add_diagnostic', ctx=Load()), + args=[ + Name(id='diagnostics', ctx=Load()), + JoinedStr( + values=[ + FormattedValue( + value=Name(id='item', ctx=Load()), + conversion=-1), + Constant(value=' in '), + FormattedValue( + value=Name(id='name', ctx=Load()), + conversion=-1), + Constant(value=' has been deleted. Glacier forks may only differ in difficulty block.')])], + keywords=[])), + Continue()])], + orelse=[], + finalbody=[]), + If( + test=Compare( + left=Name(id='item', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='BOMB_DELAY_BLOCKS')]), + body=[ + Assign( + targets=[ + Attribute( + value=Attribute( + value=Name(id='previous_item', ctx=Load()), + attr='value', + ctx=Load()), + attr='value', + ctx=Store())], + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='delay_blocks', + ctx=Load()), + slice=Name(id='fork_name', ctx=Load()), + ctx=Load()))], + orelse=[]), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='compare_ast', ctx=Load()), + args=[ + Name(id='previous_item', ctx=Load()), + Name(id='current_item', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Name(id='add_diagnostic', ctx=Load()), + args=[ + Name(id='diagnostics', ctx=Load()), + JoinedStr( + values=[ + Constant(value='`'), + FormattedValue( + value=Name(id='item', ctx=Load()), + conversion=-1), + Constant(value='` in `'), + FormattedValue( + value=Name(id='name', ctx=Load()), + conversion=-1), + Constant(value='` has changed. Glacier forks may only differ in difficulty block.')])], + keywords=[]))], + orelse=[])], + orelse=[]), + Return( + value=Name(id='diagnostics', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load()))], + decorator_list=[]), + ClassDef( + name='_Visitor', + bases=[ + Attribute( + value=Name(id='ast', ctx=Load()), + attr='NodeVisitor', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Visits nodes in a syntax tree and collects functions, classes, and\n assignments.\n ')), + AnnAssign( + target=Name(id='path', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_items', ctx=Store()), + annotation=Name(id='dict', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='path', + ctx=Store())], + value=List(elts=[], ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_items', + ctx=Store())], + value=Dict(keys=[], values=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='generic_visit', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='node', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='AST', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Called if no explicit visitor function exists for a node.\n Do not visit any child nodes.\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='sys', ctx=Load()), + attr='exit', + ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='No visit function defined for '), + FormattedValue( + value=Name(id='node', ctx=Load()), + conversion=-1), + Constant(value='. Please implement one.')])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='_insert', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='name', + annotation=Name(id='str', ctx=Load())), + arg( + arg='node', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='AST', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='item', ctx=Store())], + value=Call( + func=Attribute( + value=Constant(value='.'), + attr='join', + ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='path', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Name(id='name', ctx=Load())], + ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=Name(id='item', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_items', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='ValueError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='duplicate path '), + FormattedValue( + value=Name(id='item', ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_items', + ctx=Load()), + slice=Name(id='item', ctx=Load()), + ctx=Store())], + value=Name(id='node', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='items', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sequence of all identifiers found while visiting the source.\n ')), + Return( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_items', + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Dict', ctx=Load())), + FunctionDef( + name='visit_Module', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='module', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='Module', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit a python module.\n ')), + For( + target=Name(id='item', ctx=Store()), + iter=Subscript( + value=Attribute( + value=Name(id='module', ctx=Load()), + attr='__dict__', + ctx=Load()), + slice=Constant(value='body'), + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='visit', + ctx=Load()), + args=[ + Name(id='item', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_Import', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='import_', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='Import', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit an Import\n ')), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_ImportFrom', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='import_from', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='ImportFrom', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit an Import From\n ')), + Pass()], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_Expr', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='expr', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='Expr', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit an Expression\n ')), + If( + test=BoolOp( + op=And(), + values=[ + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Attribute( + value=Name(id='expr', ctx=Load()), + attr='value', + ctx=Load()), + Attribute( + value=Name(id='ast', ctx=Load()), + attr='Constant', + ctx=Load())], + keywords=[]), + Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='expr', ctx=Load()), + attr='value', + ctx=Load()), + attr='value', + ctx=Load()), + Name(id='str', ctx=Load())], + keywords=[])]), + body=[ + Return()], + orelse=[]), + Expr( + value=Call( + func=Name(id='print', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='The expression '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Name(id='expr', ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value=' has been ignored.')])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_AsyncFunctionDef', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='function', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='AsyncFunctionDef', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit an asynchronous function.\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_insert', + ctx=Load()), + args=[ + Attribute( + value=Name(id='function', ctx=Load()), + attr='name', + ctx=Load()), + Name(id='function', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_FunctionDef', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='function', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='FunctionDef', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit a function.\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_insert', + ctx=Load()), + args=[ + Attribute( + value=Name(id='function', ctx=Load()), + attr='name', + ctx=Load()), + Name(id='function', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_ClassDef', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='klass', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='ClassDef', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit a class.\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_insert', + ctx=Load()), + args=[ + Attribute( + value=Name(id='klass', ctx=Load()), + attr='name', + ctx=Load()), + Name(id='klass', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_Assign', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='assign', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='Assign', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit an assignment.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='assign', ctx=Load()), + attr='targets', + ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + Attribute( + value=Name(id='ast', ctx=Load()), + attr='Name', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_insert', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Attribute( + value=Name(id='assign', ctx=Load()), + attr='targets', + ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + attr='id', + ctx=Load()), + Name(id='assign', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='print', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='Assign node with target of type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Subscript( + value=Attribute( + value=Name(id='assign', ctx=Load()), + attr='targets', + ctx=Load()), + slice=Constant(value=0), + ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value=' has been ignored.')])], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_AnnAssign', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='assign', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='AnnAssign', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit an annotated assignment.\n ')), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Attribute( + value=Name(id='assign', ctx=Load()), + attr='target', + ctx=Load()), + Attribute( + value=Name(id='ast', ctx=Load()), + attr='Name', + ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_insert', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='assign', ctx=Load()), + attr='target', + ctx=Load()), + attr='id', + ctx=Load()), + Name(id='assign', ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Name(id='print', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='AnnAssign node with target of type '), + FormattedValue( + value=Call( + func=Name(id='type', ctx=Load()), + args=[ + Attribute( + value=Name(id='assign', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[]), + conversion=-1), + Constant(value=' has been ignored.')])], + keywords=[]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_If', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='node', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='If', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit an if statement.\n ')), + For( + target=Name(id='child', ctx=Store()), + iter=Attribute( + value=Name(id='node', ctx=Load()), + attr='body', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='visit', + ctx=Load()), + args=[ + Name(id='child', ctx=Load())], + keywords=[]))], + orelse=[]), + For( + target=Name(id='child', ctx=Store()), + iter=Attribute( + value=Name(id='node', ctx=Load()), + attr='orelse', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='visit', + ctx=Load()), + args=[ + Name(id='child', ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/lint/lints/glacier_forks_hygiene.v b/coq/ethereum_spec_tools/lint/lints/glacier_forks_hygiene.v new file mode 100644 index 0000000000..868bcd05e2 --- /dev/null +++ b/coq/ethereum_spec_tools/lint/lints/glacier_forks_hygiene.v @@ -0,0 +1,21 @@ +(* Generated *) +(* +Glacier Fork Hygiene Lint +^^^^^^^^^^^^^^^^^^^^^^^^^ +Ensures that the glacier forks have changes only in BOMB_DELAY_BLOCKS. +*) + + +Definition add_diagnostic (diagnostics : (* TODO type *)) (message : str) : M unit := + (* + Adds a new diagnostic message. + *) + do* M.assign "diagnostic" [[ + M.get_local ~(| "Diagnostic" |) ~(| + + |) in + ]] in + do* [[ M.get_field ~(| diagnostics, "append" |) ~(| + M.get_local ~(| "diagnostic" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum_spec_tools/lint/lints/import_hygiene.ast b/coq/ethereum_spec_tools/lint/lints/import_hygiene.ast new file mode 100644 index 0000000000..f6bc98ff75 --- /dev/null +++ b/coq/ethereum_spec_tools/lint/lints/import_hygiene.ast @@ -0,0 +1,497 @@ +Module( + body=[ + Expr( + value=Constant(value='\nImport Hygiene Lint\n^^^^^^^^^^^^^^^^^^^\n\nEnsures that the import statements follow the relevant rules.\n')), + Import( + names=[ + alias(name='ast')]), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Sequence')], + level=0), + ImportFrom( + module='ethereum_spec_tools.forks', + names=[ + alias(name='Hardfork')], + level=0), + ImportFrom( + module='ethereum_spec_tools.lint', + names=[ + alias(name='Diagnostic'), + alias(name='Lint'), + alias(name='walk_sources')], + level=0), + ClassDef( + name='ImportHygiene', + bases=[ + Name(id='Lint', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Ensures that the import statements follow the relevant rules.\n\n The rules when inside a hard fork file:\n\n - Deny absolute imports from within the active fork.\n - Deny absolute imports from future forks.\n - Deny absolute imports from active-minus-two and earlier hard forks.\n - Allow relative imports from the active hard fork.\n - Allow absolute imports from the active-minus-one hard fork.\n - Allow absolute imports of non-fork specific things.\n ')), + FunctionDef( + name='lint', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='forks', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hardfork', ctx=Load()), + ctx=Load())), + arg( + arg='position', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Walks the sources for each hardfork and emits Diagnostic messages.\n ')), + Assign( + targets=[ + Name(id='all_sources', ctx=Store())], + value=Call( + func=Name(id='dict', ctx=Load()), + args=[ + Call( + func=Name(id='walk_sources', ctx=Load()), + args=[ + Subscript( + value=Name(id='forks', ctx=Load()), + slice=Name(id='position', ctx=Load()), + ctx=Load())], + keywords=[])], + keywords=[])), + AnnAssign( + target=Name(id='diagnostics', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='name', ctx=Store()), + Name(id='source', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='all_sources', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + AugAssign( + target=Name(id='diagnostics', ctx=Store()), + op=Add(), + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='check_import', + ctx=Load()), + args=[ + Name(id='forks', ctx=Load()), + Name(id='position', ctx=Load()), + Name(id='name', ctx=Load()), + Name(id='source', ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='diagnostics', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load())), + FunctionDef( + name='check_import', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='forks', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hardfork', ctx=Load()), + ctx=Load())), + arg( + arg='position', + annotation=Name(id='int', ctx=Load())), + arg( + arg='name', + annotation=Name(id='str', ctx=Load())), + arg( + arg='source', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Checks a Python source and emits diagnostic\n messages if there are any invalid imports.\n ')), + AnnAssign( + target=Name(id='diagnostics', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='active_fork', ctx=Store())], + value=Attribute( + value=Subscript( + value=Name(id='forks', ctx=Load()), + slice=Name(id='position', ctx=Load()), + ctx=Load()), + attr='name', + ctx=Load())), + Assign( + targets=[ + Name(id='future_forks', ctx=Store())], + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + GeneratorExp( + elt=Attribute( + value=Name(id='fork', ctx=Load()), + attr='name', + ctx=Load()), + generators=[ + comprehension( + target=Name(id='fork', ctx=Store()), + iter=Subscript( + value=Name(id='forks', ctx=Load()), + slice=Slice( + lower=BinOp( + left=Name(id='position', ctx=Load()), + op=Add(), + right=Constant(value=1))), + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[])), + Assign( + targets=[ + Name(id='ancient_forks', ctx=Store())], + value=IfExp( + test=Compare( + left=Name(id='position', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=1)]), + body=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + GeneratorExp( + elt=Attribute( + value=Name(id='fork', ctx=Load()), + attr='name', + ctx=Load()), + generators=[ + comprehension( + target=Name(id='fork', ctx=Store()), + iter=Subscript( + value=Name(id='forks', ctx=Load()), + slice=Slice( + upper=BinOp( + left=Name(id='position', ctx=Load()), + op=Sub(), + right=Constant(value=1))), + ctx=Load()), + ifs=[], + is_async=0)])], + keywords=[]), + orelse=Call( + func=Name(id='tuple', ctx=Load()), + args=[], + keywords=[]))), + Assign( + targets=[ + Name(id='current_imports', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_parse', + ctx=Load()), + args=[ + Name(id='source', ctx=Load()), + Call( + func=Name(id='_Visitor', ctx=Load()), + args=[], + keywords=[]), + Constant(value='item_imports')], + keywords=[])), + For( + target=Name(id='item', ctx=Store()), + iter=Name(id='current_imports', ctx=Load()), + body=[ + If( + test=Compare( + left=Name(id='item', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Continue()], + orelse=[ + If( + test=Call( + func=Attribute( + value=Name(id='item', ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Name(id='active_fork', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='diagnostic', ctx=Store())], + value=Call( + func=Name(id='Diagnostic', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='message', + value=JoinedStr( + values=[ + Constant(value='The import `'), + FormattedValue( + value=Name(id='item', ctx=Load()), + conversion=-1), + Constant(value='` in `'), + FormattedValue( + value=Name(id='name', ctx=Load()), + conversion=-1), + Constant(value='` is from the current fork. Please use a relative import.')]))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='diagnostics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='diagnostic', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Attribute( + value=Name(id='item', ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Name(id='future_forks', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='diagnostic', ctx=Store())], + value=Call( + func=Name(id='Diagnostic', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='message', + value=JoinedStr( + values=[ + Constant(value='The import `'), + FormattedValue( + value=Name(id='item', ctx=Load()), + conversion=-1), + Constant(value='` in `'), + FormattedValue( + value=Name(id='name', ctx=Load()), + conversion=-1), + Constant(value='` is from a future fork. This is not allowed.')]))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='diagnostics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='diagnostic', ctx=Load())], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Attribute( + value=Name(id='item', ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Name(id='ancient_forks', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='diagnostic', ctx=Store())], + value=Call( + func=Name(id='Diagnostic', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='message', + value=JoinedStr( + values=[ + Constant(value='The import `'), + FormattedValue( + value=Name(id='item', ctx=Load()), + conversion=-1), + Constant(value='` in `'), + FormattedValue( + value=Name(id='name', ctx=Load()), + conversion=-1), + Constant(value='` is from an older fork. Only imports from the previous fork are allowed.')]))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='diagnostics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='diagnostic', ctx=Load())], + keywords=[]))], + orelse=[])])])])], + orelse=[]), + Return( + value=Name(id='diagnostics', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load()))], + decorator_list=[]), + ClassDef( + name='_Visitor', + bases=[ + Attribute( + value=Name(id='ast', ctx=Load()), + attr='NodeVisitor', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Visits nodes in a syntax tree and collects functions, classes, and\n assignments.\n ')), + AnnAssign( + target=Name(id='item_imports', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='item_imports', + ctx=Store())], + value=List(elts=[], ctx=Load()))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_Import', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='mod', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='Import', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit an Import.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='item_imports', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Attribute( + value=Subscript( + value=Attribute( + value=Name(id='mod', ctx=Load()), + attr='names', + ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + attr='name', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_ImportFrom', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='mod', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='ImportFrom', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit an ImportFrom.\n ')), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='item_imports', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Name(id='str', ctx=Load()), + args=[ + Attribute( + value=Name(id='mod', ctx=Load()), + attr='module', + ctx=Load())], + keywords=[])], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/lint/lints/import_hygiene.v b/coq/ethereum_spec_tools/lint/lints/import_hygiene.v new file mode 100644 index 0000000000..3d44d4fdf6 --- /dev/null +++ b/coq/ethereum_spec_tools/lint/lints/import_hygiene.v @@ -0,0 +1,8 @@ +(* Generated *) +(* +Import Hygiene Lint +^^^^^^^^^^^^^^^^^^^ + +Ensures that the import statements follow the relevant rules. +*) + diff --git a/coq/ethereum_spec_tools/lint/lints/patch_hygiene.ast b/coq/ethereum_spec_tools/lint/lints/patch_hygiene.ast new file mode 100644 index 0000000000..f52f0fee72 --- /dev/null +++ b/coq/ethereum_spec_tools/lint/lints/patch_hygiene.ast @@ -0,0 +1,858 @@ +Module( + body=[ + Expr( + value=Constant(value='\nPatch Hygiene Lint\n^^^^^^^^^^^^^^^^^^\n\nEnsures that the order of identifiers between each hardfork is consistent.\n')), + Import( + names=[ + alias(name='ast')]), + ImportFrom( + module='typing', + names=[ + alias(name='List'), + alias(name='Optional'), + alias(name='OrderedDict'), + alias(name='Sequence')], + level=0), + ImportFrom( + module='ethereum_spec_tools.forks', + names=[ + alias(name='Hardfork')], + level=0), + ImportFrom( + module='ethereum_spec_tools.lint', + names=[ + alias(name='Diagnostic'), + alias(name='Lint'), + alias(name='walk_sources')], + level=0), + ClassDef( + name='PatchHygiene', + bases=[ + Name(id='Lint', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Ensures that the order of identifiers between each hardfork is consistent.\n ')), + FunctionDef( + name='lint', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='forks', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hardfork', ctx=Load()), + ctx=Load())), + arg( + arg='position', + annotation=Name(id='int', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Walks the sources for each hardfork and emits Diagnostic messages.\n ')), + If( + test=Compare( + left=Name(id='position', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='all_previous', ctx=Store())], + value=Call( + func=Name(id='dict', ctx=Load()), + args=[ + Call( + func=Name(id='walk_sources', ctx=Load()), + args=[ + Subscript( + value=Name(id='forks', ctx=Load()), + slice=BinOp( + left=Name(id='position', ctx=Load()), + op=Sub(), + right=Constant(value=1)), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='all_current', ctx=Store())], + value=Call( + func=Name(id='dict', ctx=Load()), + args=[ + Call( + func=Name(id='walk_sources', ctx=Load()), + args=[ + Subscript( + value=Name(id='forks', ctx=Load()), + slice=Name(id='position', ctx=Load()), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='items', ctx=Store())], + value=GeneratorExp( + elt=Tuple( + elts=[ + Name(id='k', ctx=Load()), + Name(id='v', ctx=Load()), + Call( + func=Attribute( + value=Name(id='all_previous', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='k', ctx=Load()), + Constant(value=None)], + keywords=[])], + ctx=Load()), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='v', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='all_current', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='diagnostics', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='name', ctx=Store()), + Name(id='current', ctx=Store()), + Name(id='previous', ctx=Store())], + ctx=Store()), + iter=Name(id='items', ctx=Load()), + body=[ + AugAssign( + target=Name(id='diagnostics', ctx=Store()), + op=Add(), + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='compare', + ctx=Load()), + args=[ + Name(id='name', ctx=Load()), + Name(id='current', ctx=Load()), + Name(id='previous', ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='diagnostics', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load())), + FunctionDef( + name='compare', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='name', + annotation=Name(id='str', ctx=Load())), + arg( + arg='current_source', + annotation=Name(id='str', ctx=Load())), + arg( + arg='previous_source', + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Compares two strings containing Python source and emits diagnostic\n messages if any identifiers have changed relative positions.\n ')), + If( + test=Compare( + left=Name(id='previous_source', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='current_nodes', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_parse', + ctx=Load()), + args=[ + Name(id='current_source', ctx=Load()), + Call( + func=Name(id='_Visitor', ctx=Load()), + args=[], + keywords=[]), + Constant(value='items')], + keywords=[])), + Assign( + targets=[ + Name(id='previous_nodes', ctx=Store())], + value=DictComp( + key=Name(id='item', ctx=Load()), + value=Name(id='idx', ctx=Load()), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='idx', ctx=Store()), + Name(id='item', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='enumerate', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_parse', + ctx=Load()), + args=[ + Name(id='previous_source', ctx=Load()), + Call( + func=Name(id='_Visitor', ctx=Load()), + args=[], + keywords=[]), + Constant(value='items')], + keywords=[])], + keywords=[]), + ifs=[], + is_async=0)])), + AnnAssign( + target=Name(id='diagnostics', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + Assign( + targets=[ + Name(id='maximum', ctx=Store())], + value=Constant(value=None)), + For( + target=Name(id='item', ctx=Store()), + iter=Name(id='current_nodes', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='previous_position', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='previous_nodes', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='item', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='previous_position', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Continue()], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='maximum', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + Compare( + left=Name(id='previous_position', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Name(id='maximum', ctx=Load())])]), + body=[ + Assign( + targets=[ + Name(id='maximum', ctx=Store())], + value=Name(id='previous_position', ctx=Load()))], + orelse=[ + If( + test=Compare( + left=Name(id='previous_position', ctx=Load()), + ops=[ + LtE()], + comparators=[ + Name(id='maximum', ctx=Load())]), + body=[ + Assign( + targets=[ + Name(id='diagnostic', ctx=Store())], + value=Call( + func=Name(id='Diagnostic', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='message', + value=JoinedStr( + values=[ + Constant(value='the item `'), + FormattedValue( + value=Name(id='item', ctx=Load()), + conversion=-1), + Constant(value='` in `'), + FormattedValue( + value=Name(id='name', ctx=Load()), + conversion=-1), + Constant(value='` has changed relative positions')]))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='diagnostics', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='diagnostic', ctx=Load())], + keywords=[]))], + orelse=[])])], + orelse=[]), + Return( + value=Name(id='diagnostics', ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Diagnostic', ctx=Load()), + ctx=Load()))], + decorator_list=[]), + ClassDef( + name='_Visitor', + bases=[ + Attribute( + value=Name(id='ast', ctx=Load()), + attr='NodeVisitor', + ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Visits nodes in a syntax tree and collects functions, classes, and\n assignments.\n ')), + AnnAssign( + target=Name(id='path', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='_items', ctx=Store()), + annotation=Constant(value='OrderedDict[str, None]'), + simple=1), + AnnAssign( + target=Name(id='in_assign', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='path', + ctx=Store())], + value=List(elts=[], ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_items', + ctx=Store())], + value=Call( + func=Name(id='OrderedDict', ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='in_assign', + ctx=Store())], + value=Constant(value=0))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='_insert', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='item', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Name(id='item', ctx=Store())], + value=Call( + func=Attribute( + value=Constant(value='.'), + attr='join', + ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='path', + ctx=Load()), + op=Add(), + right=List( + elts=[ + Name(id='item', ctx=Load())], + ctx=Load()))], + keywords=[])), + If( + test=Compare( + left=Name(id='item', ctx=Load()), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='_items', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='ValueError', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='duplicate path '), + FormattedValue( + value=Name(id='item', ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_items', + ctx=Load()), + slice=Name(id='item', ctx=Load()), + ctx=Store())], + value=Constant(value=None))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='items', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Sequence of all identifiers found while visiting the source.\n ')), + Return( + value=Call( + func=Name(id='list', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='_items', + ctx=Load()), + attr='keys', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Subscript( + value=Name(id='Sequence', ctx=Load()), + slice=Name(id='str', ctx=Load()), + ctx=Load())), + FunctionDef( + name='visit_AsyncFunctionDef', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='function', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='AsyncFunctionDef', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit an asynchronous function.\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_insert', + ctx=Load()), + args=[ + Attribute( + value=Name(id='function', ctx=Load()), + attr='name', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_FunctionDef', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='function', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='FunctionDef', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit a function.\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_insert', + ctx=Load()), + args=[ + Attribute( + value=Name(id='function', ctx=Load()), + attr='name', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_ClassDef', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='klass', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='ClassDef', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit a class.\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_insert', + ctx=Load()), + args=[ + Attribute( + value=Name(id='klass', ctx=Load()), + attr='name', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='path', + ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Attribute( + value=Name(id='klass', ctx=Load()), + attr='name', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='generic_visit', + ctx=Load()), + args=[ + Name(id='klass', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='got', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='path', + ctx=Load()), + attr='pop', + ctx=Load()), + args=[], + keywords=[])), + Assert( + test=Compare( + left=Attribute( + value=Name(id='klass', ctx=Load()), + attr='name', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Name(id='got', ctx=Load())]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_Assign', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='assign', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='Assign', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit an assignment.\n ')), + AugAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='in_assign', + ctx=Store()), + op=Add(), + value=Constant(value=1)), + For( + target=Name(id='target', ctx=Store()), + iter=Attribute( + value=Name(id='assign', ctx=Load()), + attr='targets', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='visit', + ctx=Load()), + args=[ + Name(id='target', ctx=Load())], + keywords=[]))], + orelse=[]), + AugAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='in_assign', + ctx=Store()), + op=Sub(), + value=Constant(value=1)), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='visit', + ctx=Load()), + args=[ + Attribute( + value=Name(id='assign', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_AnnAssign', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='assign', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='AnnAssign', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit an annotated assignment.\n ')), + AugAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='in_assign', + ctx=Store()), + op=Add(), + value=Constant(value=1)), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='visit', + ctx=Load()), + args=[ + Attribute( + value=Name(id='assign', ctx=Load()), + attr='target', + ctx=Load())], + keywords=[])), + AugAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='in_assign', + ctx=Store()), + op=Sub(), + value=Constant(value=1)), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='visit', + ctx=Load()), + args=[ + Attribute( + value=Name(id='assign', ctx=Load()), + attr='annotation', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='assign', ctx=Load()), + attr='value', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='visit', + ctx=Load()), + args=[ + Attribute( + value=Name(id='assign', ctx=Load()), + attr='value', + ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='visit_Name', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='identifier', + annotation=Attribute( + value=Name(id='ast', ctx=Load()), + attr='Name', + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Visit an identifier.\n ')), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='in_assign', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='_insert', + ctx=Load()), + args=[ + Attribute( + value=Name(id='identifier', ctx=Load()), + attr='id', + ctx=Load())], + keywords=[]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/lint/lints/patch_hygiene.v b/coq/ethereum_spec_tools/lint/lints/patch_hygiene.v new file mode 100644 index 0000000000..1718a0191c --- /dev/null +++ b/coq/ethereum_spec_tools/lint/lints/patch_hygiene.v @@ -0,0 +1,8 @@ +(* Generated *) +(* +Patch Hygiene Lint +^^^^^^^^^^^^^^^^^^ + +Ensures that the order of identifiers between each hardfork is consistent. +*) + diff --git a/coq/ethereum_spec_tools/new_fork.ast b/coq/ethereum_spec_tools/new_fork.ast new file mode 100644 index 0000000000..b187cad2db --- /dev/null +++ b/coq/ethereum_spec_tools/new_fork.ast @@ -0,0 +1,828 @@ +Module( + body=[ + Expr( + value=Constant(value='\nTool to create a new fork using the latest fork\n')), + Import( + names=[ + alias(name='argparse')]), + Import( + names=[ + alias(name='fnmatch')]), + Import( + names=[ + alias(name='os')]), + Import( + names=[ + alias(name='re')]), + ImportFrom( + module='shutil', + names=[ + alias(name='copytree')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Tuple')], + level=0), + Assign( + targets=[ + Name(id='DESCRIPTION', ctx=Store())], + value=Constant(value='\nCreates the base code for a new fork by using the existing code from a given fork.\n\n\nThe ethereum-spec-new-fork command takes 4 arguments, 2 of which are optional\n from_fork: The fork name from which the code is to be duplicated Eg - "Tangerine Whistle"\n to_fork: The fork name of the new fork Eg - "Spurious Dragon"\n from_test(Optional): Name of the from fork within the test fixtures in case it is different from fork name Eg - "EIP150"\n to_test(Optional): Name of the to fork within the test fixtures in case it is different from fork name Eg - "EIP158"\n\n\nIf one wants to create the spurious dragon fork from the tangerine whistle one\n ethereum-spec-new-fork --from_fork="Tangerine Whistle" --to_fork="Spurious Dragon" --from_test=EIP150 --to_test=EIP158\n\nThe following will have to however, be updated manually\n 1. The fork number and MAINNET_FORK_BLOCK in __init__.py\n 2. Any absolute package imports from other forks eg. in trie.py\n 3. Package Names under setup.cfg\n 4. Add the new fork to the monkey_patch() function in src/ethereum_optimized/__init__.py\n 5. Adjust the underline in fork/__init__.py\n')), + Assign( + targets=[ + Name(id='parser', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='ArgumentParser', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='description', + value=Name(id='DESCRIPTION', ctx=Load())), + keyword( + arg='formatter_class', + value=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='RawDescriptionHelpFormatter', + ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--from_fork')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='from_fork')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='required', + value=Constant(value=True))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--to_fork')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='to_fork')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='required', + value=Constant(value=True))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--from_test')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='from_test')), + keyword( + arg='type', + value=Name(id='str', ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--to_test')], + keywords=[ + keyword( + arg='dest', + value=Constant(value='to_test')), + keyword( + arg='type', + value=Name(id='str', ctx=Load()))])), + FunctionDef( + name='find_replace', + args=arguments( + posonlyargs=[], + args=[ + arg( + arg='dir', + annotation=Name(id='str', ctx=Load())), + arg( + arg='find', + annotation=Name(id='str', ctx=Load())), + arg( + arg='replace', + annotation=Name(id='str', ctx=Load())), + arg( + arg='file_pattern', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Replace the occurrence of a certain text in files with a new text\n ')), + For( + target=Tuple( + elts=[ + Name(id='path', ctx=Store()), + Name(id='_', ctx=Store()), + Name(id='files', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='os', ctx=Load()), + attr='walk', + ctx=Load()), + args=[ + Name(id='dir', ctx=Load())], + keywords=[]), + body=[ + For( + target=Name(id='filename', ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='fnmatch', ctx=Load()), + attr='filter', + ctx=Load()), + args=[ + Name(id='files', ctx=Load()), + Name(id='file_pattern', ctx=Load())], + keywords=[]), + body=[ + Assign( + targets=[ + Name(id='file_path', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='os', ctx=Load()), + attr='path', + ctx=Load()), + attr='join', + ctx=Load()), + args=[ + Name(id='path', ctx=Load()), + Name(id='filename', ctx=Load())], + keywords=[])), + With( + items=[ + withitem( + context_expr=Call( + func=Name(id='open', ctx=Load()), + args=[ + Name(id='file_path', ctx=Load()), + Constant(value='r+b')], + keywords=[]), + optional_vars=Name(id='f', ctx=Store()))], + body=[ + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='f', ctx=Load()), + attr='read', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='find_pattern', ctx=Store())], + value=Call( + func=Attribute( + value=BinOp( + left=BinOp( + left=Constant(value='\\b'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='re', ctx=Load()), + attr='escape', + ctx=Load()), + args=[ + Name(id='find', ctx=Load())], + keywords=[])), + op=Add(), + right=Constant(value='\\b')), + attr='encode', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='s', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='re', ctx=Load()), + attr='sub', + ctx=Load()), + args=[ + Name(id='find_pattern', ctx=Load()), + Call( + func=Attribute( + value=Name(id='replace', ctx=Load()), + attr='encode', + ctx=Load()), + args=[], + keywords=[]), + Name(id='s', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='f', ctx=Load()), + attr='seek', + ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='f', ctx=Load()), + attr='write', + ctx=Load()), + args=[ + Name(id='s', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='f', ctx=Load()), + attr='truncate', + ctx=Load()), + args=[], + keywords=[]))])], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + ClassDef( + name='ForkCreator', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Object to create base code for a new fork from the previous fork.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='from_fork', + annotation=Name(id='str', ctx=Load())), + arg( + arg='to_fork', + annotation=Name(id='str', ctx=Load())), + arg( + arg='from_test_names', + annotation=Name(id='str', ctx=Load())), + arg( + arg='to_test_names', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='package_folder', + ctx=Store())], + value=Constant(value='src/ethereum')), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='test_folder', + ctx=Store())], + value=Constant(value='tests')), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='from_fork', + ctx=Store()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='from_package', + ctx=Store()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='from_path', + ctx=Store()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='from_test_path', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='get_fork_paths', + ctx=Load()), + args=[ + Name(id='from_fork', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Tuple( + elts=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_fork', + ctx=Store()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_package', + ctx=Store()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_path', + ctx=Store()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_test_path', + ctx=Store())], + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='get_fork_paths', + ctx=Load()), + args=[ + Name(id='to_fork', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='from_test_names', + ctx=Store())], + value=Name(id='from_test_names', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_test_names', + ctx=Store())], + value=Name(id='to_test_names', ctx=Load()))], + decorator_list=[]), + FunctionDef( + name='get_fork_paths', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='fork', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Get the relevant paths for all folders in a particular fork.\n ')), + Assign( + targets=[ + Name(id='name', ctx=Store())], + value=Name(id='fork', ctx=Load())), + Assign( + targets=[ + Name(id='package', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='name', ctx=Load()), + attr='replace', + ctx=Load()), + args=[ + Constant(value=' '), + Constant(value='_')], + keywords=[]), + attr='lower', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='path', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='os', ctx=Load()), + attr='path', + ctx=Load()), + attr='join', + ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='package_folder', + ctx=Load()), + Name(id='package', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='test_path', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='os', ctx=Load()), + attr='path', + ctx=Load()), + attr='join', + ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='test_folder', + ctx=Load()), + Name(id='package', ctx=Load())], + keywords=[])), + Return( + value=Tuple( + elts=[ + Name(id='name', ctx=Load()), + Name(id='package', ctx=Load()), + Name(id='path', ctx=Load()), + Name(id='test_path', ctx=Load())], + ctx=Load()))], + decorator_list=[], + returns=Subscript( + value=Name(id='Tuple', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='str', ctx=Load()), + Constant(value=Ellipsis)], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='duplicate_fork', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Copy the relevant files/folders from the old fork\n ')), + Expr( + value=Call( + func=Name(id='copytree', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='from_path', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_path', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Name(id='copytree', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='from_test_path', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_test_path', + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='update_new_fork_contents', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Replace references to the old fork with the new ones\n The following however, will have to be updated manually\n 1. The fork number and MAINNET_FORK_BLOCK in __init__.py\n 2. Any absolute package imports from other forks eg. in trie.py\n 3. Package Names under setup.cfg\n ')), + Expr( + value=Call( + func=Name(id='find_replace', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_path', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='from_fork', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_fork', + ctx=Load()), + Constant(value='*.py')], + keywords=[])), + Expr( + value=Call( + func=Name(id='find_replace', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_path', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='from_package', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_package', + ctx=Load()), + Constant(value='*.py')], + keywords=[])), + Expr( + value=Call( + func=Name(id='find_replace', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_path', + ctx=Load()), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='from_fork', + ctx=Load()), + attr='lower', + ctx=Load()), + args=[], + keywords=[]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='to_fork', + ctx=Load()), + attr='lower', + ctx=Load()), + args=[], + keywords=[]), + Constant(value='*.py')], + keywords=[])), + Expr( + value=Call( + func=Name(id='find_replace', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_test_path', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='from_test_names', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_test_names', + ctx=Load()), + Constant(value='*.py')], + keywords=[])), + Expr( + value=Call( + func=Name(id='find_replace', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_test_path', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='from_fork', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_fork', + ctx=Load()), + Constant(value='*.py')], + keywords=[])), + Expr( + value=Call( + func=Name(id='find_replace', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_test_path', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='from_package', + ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_package', + ctx=Load()), + Constant(value='*.py')], + keywords=[])), + Expr( + value=Call( + func=Name(id='find_replace', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='to_test_path', + ctx=Load()), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='from_fork', + ctx=Load()), + attr='lower', + ctx=Load()), + args=[], + keywords=[]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='to_fork', + ctx=Load()), + attr='lower', + ctx=Load()), + args=[], + keywords=[]), + Constant(value='*.py')], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + FunctionDef( + name='main', + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create the new fork\n ')), + Assign( + targets=[ + Name(id='options', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='parse_args', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='from_fork', ctx=Store())], + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='from_fork', + ctx=Load())), + Assign( + targets=[ + Name(id='to_fork', ctx=Store())], + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='to_fork', + ctx=Load())), + Assign( + targets=[ + Name(id='from_test', ctx=Store())], + value=IfExp( + test=Compare( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='from_test', + ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=Name(id='from_fork', ctx=Load()), + orelse=Attribute( + value=Name(id='options', ctx=Load()), + attr='from_test', + ctx=Load()))), + Assign( + targets=[ + Name(id='to_test', ctx=Store())], + value=IfExp( + test=Compare( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='to_test', + ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=Name(id='to_fork', ctx=Load()), + orelse=Attribute( + value=Name(id='options', ctx=Load()), + attr='to_test', + ctx=Load()))), + Assign( + targets=[ + Name(id='fork_creator', ctx=Store())], + value=Call( + func=Name(id='ForkCreator', ctx=Load()), + args=[ + Name(id='from_fork', ctx=Load()), + Name(id='to_fork', ctx=Load()), + Name(id='from_test', ctx=Load()), + Name(id='to_test', ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='fork_creator', ctx=Load()), + attr='duplicate_fork', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='fork_creator', ctx=Load()), + attr='update_new_fork_contents', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='final_help_text', ctx=Store())], + value=Call( + func=Attribute( + value=Constant(value='\nFork `{fork}` has been successfully created.\n\nPLEASE REMEMBER TO UPDATE THE FOLLOWING MANUALLY:\n 1. The fork number and MAINNET_FORK_BLOCK in __init__.py. If you are proposing a new EIP, please set MAINNET_FORK_BLOCK to None.\n 2. Any absolute package imports from other forks. Eg. in trie.py\n 3. Package Names under setup.cfg\n 4. Add the new fork to the monkey_patch() function in src/ethereum_optimized/__init__.py\n 5. Adjust the underline in src/{package}/__init__.py\n'), + attr='format', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='fork', + value=Attribute( + value=Name(id='fork_creator', ctx=Load()), + attr='to_fork', + ctx=Load())), + keyword( + arg='package', + value=Attribute( + value=Name(id='fork_creator', ctx=Load()), + attr='to_package', + ctx=Load()))])), + Expr( + value=Call( + func=Name(id='print', ctx=Load()), + args=[ + Name(id='final_help_text', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + If( + test=Compare( + left=Name(id='__name__', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='__main__')]), + body=[ + Expr( + value=Call( + func=Name(id='main', ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/new_fork.v b/coq/ethereum_spec_tools/new_fork.v new file mode 100644 index 0000000000..4b70985b9c --- /dev/null +++ b/coq/ethereum_spec_tools/new_fork.v @@ -0,0 +1,57 @@ +(* Generated *) +(* +Tool to create a new fork using the latest fork +*) + + +Definition find_replace (dir : str) (find : str) (replace : str) (file_pattern : str) : M unit := + (* + Replace the occurrence of a certain text in files with a new text + *) + (* TODO statement *) + M.pure tt. + +Definition main : M unit := + (* + Create the new fork + *) + do* M.assign "options" [[ + M.get_field ~(| M.get_local ~(| "parser" |), "parse_args" |) ~(| + + |) in + ]] in + do* M.assign "from_fork" [[ + M.get_field ~(| M.get_local ~(| "options" |), "from_fork" |) in + ]] in + do* M.assign "to_fork" [[ + M.get_field ~(| M.get_local ~(| "options" |), "to_fork" |) in + ]] in + do* M.assign "from_test" [[ + (* TODO expression *) in + ]] in + do* M.assign "to_test" [[ + (* TODO expression *) in + ]] in + do* M.assign "fork_creator" [[ + M.get_local ~(| "ForkCreator" |) ~(| + M.get_local ~(| "from_fork" |), + M.get_local ~(| "to_fork" |), + M.get_local ~(| "from_test" |), + M.get_local ~(| "to_test" |) + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "fork_creator" |), "duplicate_fork" |) ~(| + + |) ]] in + do* [[ M.get_field ~(| M.get_local ~(| "fork_creator" |), "update_new_fork_contents" |) ~(| + + |) ]] in + do* M.assign "final_help_text" [[ + M.get_field ~(| (* TODO constant *), "format" |) ~(| + + |) in + ]] in + do* [[ M.get_local ~(| "print" |) ~(| + M.get_local ~(| "final_help_text" |) + |) ]] in + M.pure tt. diff --git a/coq/ethereum_spec_tools/patch_tool.ast b/coq/ethereum_spec_tools/patch_tool.ast new file mode 100644 index 0000000000..5b25575cca --- /dev/null +++ b/coq/ethereum_spec_tools/patch_tool.ast @@ -0,0 +1,379 @@ +Module( + body=[ + Expr( + value=Constant(value='\nSimple patching tool\n')), + Import( + names=[ + alias(name='argparse')]), + Import( + names=[ + alias(name='subprocess')]), + ImportFrom( + module='sys', + names=[ + alias(name='stderr'), + alias(name='stdout')], + level=0), + Assign( + targets=[ + Name(id='DESCRIPTION', ctx=Store())], + value=Constant(value="\nApply the unstaged changes in SOURCE_FORK to each TARGET_FORK. If some of the\nchange didn't apply, '.rej' files listing the unapplied changes will be left in\nTARGET_FORK.\n")), + Assign( + targets=[ + Name(id='parser', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='ArgumentParser', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='description', + value=Name(id='DESCRIPTION', ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='source_fork')], + keywords=[ + keyword( + arg='metavar', + value=Constant(value='SOURCE_FORK')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='nargs', + value=Constant(value=1))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='targets')], + keywords=[ + keyword( + arg='metavar', + value=Constant(value='TARGET_FORK')), + keyword( + arg='type', + value=Name(id='str', ctx=Load())), + keyword( + arg='nargs', + value=Constant(value='*'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--tests')], + keywords=[ + keyword( + arg='action', + value=Constant(value='store_const')), + keyword( + arg='const', + value=Constant(value='tests/')), + keyword( + arg='dest', + value=Constant(value='prefix')), + keyword( + arg='help', + value=Constant(value='Patch the tests instead'))])), + FunctionDef( + name='main', + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Patch the changes from one fork into the others.\n ')), + Assign( + targets=[ + Name(id='options', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='parse_args', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Name(id='options', ctx=Load()), + attr='prefix', + ctx=Load())), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='options', ctx=Load()), + attr='prefix', + ctx=Store())], + value=Constant(value='src/ethereum/'))], + orelse=[]), + Assign( + targets=[ + Name(id='source_fork_path', ctx=Store())], + value=BinOp( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='prefix', + ctx=Load()), + op=Add(), + right=Subscript( + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='source_fork', + ctx=Load()), + slice=Constant(value=0), + ctx=Load()))), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='options', ctx=Load()), + attr='prefix', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='tests/')]), + Compare( + left=Constant(value='dao_fork'), + ops=[ + In()], + comparators=[ + Attribute( + value=Name(id='options', ctx=Load()), + attr='targets', + ctx=Load())])]), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value='dao_fork has no tests')], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='git_diff', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='subprocess', ctx=Load()), + attr='run', + ctx=Load()), + args=[ + List( + elts=[ + Constant(value='git'), + Constant(value='diff'), + Name(id='source_fork_path', ctx=Load())], + ctx=Load())], + keywords=[ + keyword( + arg='capture_output', + value=Constant(value=True)), + keyword( + arg='text', + value=Constant(value=True))])), + Assign( + targets=[ + Name(id='output_lines', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='git_diff', ctx=Load()), + attr='stdout', + ctx=Load()), + attr='splitlines', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='keepends', + value=Constant(value=True))])), + For( + target=Name(id='target', ctx=Store()), + iter=Attribute( + value=Name(id='options', ctx=Load()), + attr='targets', + ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='patch', ctx=Store())], + value=Constant(value='')), + For( + target=Name(id='line', ctx=Store()), + iter=Name(id='output_lines', ctx=Load()), + body=[ + If( + test=Call( + func=Attribute( + value=Name(id='line', ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Constant(value='diff --git')], + keywords=[]), + body=[ + Pass()], + orelse=[ + If( + test=Call( + func=Attribute( + value=Name(id='line', ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Constant(value='index')], + keywords=[]), + body=[ + Pass()], + orelse=[ + If( + test=Call( + func=Attribute( + value=Name(id='line', ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Constant(value='--- a/')], + keywords=[]), + body=[ + AugAssign( + target=Name(id='patch', ctx=Store()), + op=Add(), + value=Call( + func=Attribute( + value=Name(id='line', ctx=Load()), + attr='replace', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value='--- a/'), + op=Add(), + right=Attribute( + value=Name(id='options', ctx=Load()), + attr='prefix', + ctx=Load())), + op=Add(), + right=Subscript( + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='source_fork', + ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + BinOp( + left=BinOp( + left=Constant(value='--- '), + op=Add(), + right=Attribute( + value=Name(id='options', ctx=Load()), + attr='prefix', + ctx=Load())), + op=Add(), + right=Name(id='target', ctx=Load()))], + keywords=[]))], + orelse=[ + If( + test=Call( + func=Attribute( + value=Name(id='line', ctx=Load()), + attr='startswith', + ctx=Load()), + args=[ + Constant(value='+++ b/')], + keywords=[]), + body=[ + AugAssign( + target=Name(id='patch', ctx=Store()), + op=Add(), + value=Call( + func=Attribute( + value=Name(id='line', ctx=Load()), + attr='replace', + ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Constant(value='+++ b/'), + op=Add(), + right=Attribute( + value=Name(id='options', ctx=Load()), + attr='prefix', + ctx=Load())), + op=Add(), + right=Subscript( + value=Attribute( + value=Name(id='options', ctx=Load()), + attr='source_fork', + ctx=Load()), + slice=Constant(value=0), + ctx=Load())), + BinOp( + left=BinOp( + left=Constant(value='+++ '), + op=Add(), + right=Attribute( + value=Name(id='options', ctx=Load()), + attr='prefix', + ctx=Load())), + op=Add(), + right=Name(id='target', ctx=Load()))], + keywords=[]))], + orelse=[ + AugAssign( + target=Name(id='patch', ctx=Store()), + op=Add(), + value=Name(id='line', ctx=Load()))])])])])], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='subprocess', ctx=Load()), + attr='run', + ctx=Load()), + args=[ + List( + elts=[ + Constant(value='patch'), + Constant(value='-p0'), + Constant(value='--no-backup-if-mismatch')], + ctx=Load())], + keywords=[ + keyword( + arg='input', + value=Name(id='patch', ctx=Load())), + keyword( + arg='text', + value=Constant(value=True)), + keyword( + arg='stdout', + value=Name(id='stdout', ctx=Load())), + keyword( + arg='stderr', + value=Name(id='stderr', ctx=Load()))]))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None))], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/patch_tool.v b/coq/ethereum_spec_tools/patch_tool.v new file mode 100644 index 0000000000..7f6d94d952 --- /dev/null +++ b/coq/ethereum_spec_tools/patch_tool.v @@ -0,0 +1,32 @@ +(* Generated *) +(* +Simple patching tool +*) + + +Definition main : M unit := + (* + Patch the changes from one fork into the others. + *) + do* M.assign "options" [[ + M.get_field ~(| M.get_local ~(| "parser" |), "parse_args" |) ~(| + + |) in + ]] in + (* TODO statement *) + do* M.assign "source_fork_path" [[ + (* TODO expression *) in + ]] in + (* TODO statement *) + do* M.assign "git_diff" [[ + M.get_field ~(| M.get_local ~(| "subprocess" |), "run" |) ~(| + (* TODO expression *) + |) in + ]] in + do* M.assign "output_lines" [[ + M.get_field ~(| M.get_field ~(| M.get_local ~(| "git_diff" |), "stdout" |), "splitlines" |) ~(| + + |) in + ]] in + (* TODO statement *) + M.pure tt. diff --git a/coq/ethereum_spec_tools/sync.ast b/coq/ethereum_spec_tools/sync.ast new file mode 100644 index 0000000000..fd1fbc57ac --- /dev/null +++ b/coq/ethereum_spec_tools/sync.ast @@ -0,0 +1,5912 @@ +Module( + body=[ + Expr( + value=Constant(value='\nEthereum Sync\n^^^^^^^^^^^^^\n\nUsing an RPC provider, fetch each block and validate it with the specification.\n')), + Import( + names=[ + alias(name='argparse')]), + Import( + names=[ + alias(name='json')]), + Import( + names=[ + alias(name='logging')]), + Import( + names=[ + alias(name='os')]), + Import( + names=[ + alias(name='pkgutil')]), + Import( + names=[ + alias(name='shutil')]), + Import( + names=[ + alias(name='time')]), + ImportFrom( + module='queue', + names=[ + alias(name='Empty'), + alias(name='Full'), + alias(name='Queue')], + level=0), + ImportFrom( + module='threading', + names=[ + alias(name='Thread')], + level=0), + ImportFrom( + module='typing', + names=[ + alias(name='Any'), + alias(name='Dict'), + alias(name='List'), + alias(name='Optional'), + alias(name='TypeVar'), + alias(name='Union'), + alias(name='cast')], + level=0), + ImportFrom( + module='urllib', + names=[ + alias(name='request')], + level=0), + ImportFrom( + module='ethereum_types.bytes', + names=[ + alias(name='Bytes0'), + alias(name='Bytes256')], + level=0), + ImportFrom( + module='ethereum_types.numeric', + names=[ + alias(name='U64'), + alias(name='U256'), + alias(name='Uint')], + level=0), + ImportFrom( + module='ethereum', + names=[ + alias(name='genesis'), + alias(name='rlp')], + level=0), + ImportFrom( + module='ethereum.utils.hexadecimal', + names=[ + alias(name='hex_to_bytes'), + alias(name='hex_to_bytes8'), + alias(name='hex_to_bytes32'), + alias(name='hex_to_u64'), + alias(name='hex_to_u256'), + alias(name='hex_to_uint')], + level=0), + ImportFrom( + module='forks', + names=[ + alias(name='Hardfork')], + level=1), + Assign( + targets=[ + Name(id='T', ctx=Store())], + value=Call( + func=Name(id='TypeVar', ctx=Load()), + args=[ + Constant(value='T')], + keywords=[])), + ClassDef( + name='RpcError', + bases=[ + Name(id='Exception', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Error message and code returned by the RPC provider.\n ')), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='code', + annotation=Name(id='int', ctx=Load())), + arg( + arg='message', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='super', ctx=Load()), + args=[], + keywords=[]), + attr='__init__', + ctx=Load()), + args=[ + Name(id='message', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='code', + ctx=Store())], + value=Name(id='code', ctx=Load()))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + ClassDef( + name='ForkTracking', + bases=[], + keywords=[], + body=[ + Expr( + value=Constant(value='\n Enables subclasses to track the current fork.\n ')), + AnnAssign( + target=Name(id='forks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hardfork', ctx=Load()), + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='block_number', ctx=Store()), + annotation=Name(id='Uint', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='active_fork_index', ctx=Store()), + annotation=Name(id='int', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='forks', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hardfork', ctx=Load()), + ctx=Load())), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='forks', + ctx=Store())], + value=Name(id='forks', ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='set_block', + ctx=Load()), + args=[ + Name(id='block_number', ctx=Load()), + Name(id='block_timestamp', ctx=Load())], + keywords=[]))], + decorator_list=[]), + FunctionDef( + name='active_fork', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Currently executing hard fork.\n ')), + Return( + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='forks', + ctx=Load()), + slice=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork_index', + ctx=Load()), + ctx=Load()))], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Name(id='Hardfork', ctx=Load())), + FunctionDef( + name='next_fork', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Hard fork that follows the currently executing hard fork.\n ')), + Try( + body=[ + Return( + value=Subscript( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='forks', + ctx=Load()), + slice=BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork_index', + ctx=Load()), + op=Add(), + right=Constant(value=1)), + ctx=Load()))], + handlers=[ + ExceptHandler( + type=Name(id='IndexError', ctx=Load()), + body=[ + Return( + value=Constant(value=None))])], + orelse=[], + finalbody=[])], + decorator_list=[ + Name(id='property', ctx=Load())], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Hardfork', ctx=Load()), + ctx=Load())), + FunctionDef( + name='module', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='name', + annotation=Name(id='str', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Return a module from the current hard fork.\n ')), + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork', + ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Name(id='name', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='set_block', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='block_number', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='block_timestamp', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Set the block number and switch to the correct fork.')), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Store())], + value=Name(id='block_number', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork_index', + ctx=Store())], + value=Constant(value=0)), + While( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='next_fork', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='next_fork', + ctx=Load()), + attr='has_activated', + ctx=Load()), + args=[ + Name(id='block_number', ctx=Load()), + Name(id='block_timestamp', ctx=Load())], + keywords=[])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork_index', + ctx=Store()), + op=Add(), + value=Constant(value=1))], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='advance_block', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='timestamp', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='Increment the block number, return `True` if the fork changed.')), + AugAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Store()), + op=Add(), + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Assign( + targets=[ + Name(id='new_fork', ctx=Store())], + value=Constant(value=False)), + While( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='next_fork', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='next_fork', + ctx=Load()), + attr='has_activated', + ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load()), + Name(id='timestamp', ctx=Load())], + keywords=[])]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork_index', + ctx=Store()), + op=Add(), + value=Constant(value=1)), + Assign( + targets=[ + Name(id='new_fork', ctx=Store())], + value=Constant(value=True))], + orelse=[]), + Return( + value=Name(id='new_fork', ctx=Load()))], + decorator_list=[], + returns=Name(id='bool', ctx=Load()))], + decorator_list=[]), + ClassDef( + name='BlockDownloader', + bases=[ + Name(id='ForkTracking', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='Downloads blocks from the RPC provider.')), + AnnAssign( + target=Name(id='queue', ctx=Store()), + annotation=Name(id='Queue', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='log', ctx=Store()), + annotation=Attribute( + value=Name(id='logging', ctx=Load()), + attr='Logger', + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='rpc_url', ctx=Store()), + annotation=Name(id='str', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='geth', ctx=Store()), + annotation=Name(id='bool', ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='forks', + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Name(id='Hardfork', ctx=Load()), + ctx=Load())), + arg( + arg='log', + annotation=Attribute( + value=Name(id='logging', ctx=Load()), + attr='Logger', + ctx=Load())), + arg( + arg='rpc_url', + annotation=Name(id='str', ctx=Load())), + arg( + arg='geth', + annotation=Name(id='bool', ctx=Load())), + arg( + arg='first_block', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='first_block_timestamp', + annotation=Name(id='U256', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='ForkTracking', ctx=Load()), + attr='__init__', + ctx=Load()), + args=[ + Name(id='self', ctx=Load()), + Name(id='forks', ctx=Load()), + Name(id='first_block', ctx=Load()), + Name(id='first_block_timestamp', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork_index', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Constant(value=0)]), + body=[ + AugAssign( + target=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork_index', + ctx=Store()), + op=Sub(), + value=Constant(value=1))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='queue', + ctx=Store())], + value=Call( + func=Name(id='Queue', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='maxsize', + value=Constant(value=512))])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Store())], + value=Name(id='log', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='rpc_url', + ctx=Store())], + value=Name(id='rpc_url', ctx=Load())), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='geth', + ctx=Store())], + value=Name(id='geth', ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Call( + func=Name(id='Thread', ctx=Load()), + args=[], + keywords=[ + keyword( + arg='target', + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='download', + ctx=Load())), + keyword( + arg='name', + value=Constant(value='download')), + keyword( + arg='daemon', + value=Constant(value=True))]), + attr='start', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='take_block', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Pop a block of the download queue.\n ')), + While( + test=Constant(value=True), + body=[ + Try( + body=[ + Return( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='queue', + ctx=Load()), + attr='get', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='timeout', + value=Constant(value=1))]))], + handlers=[ + ExceptHandler( + type=Name(id='Empty', ctx=Load()), + body=[ + Pass()])], + orelse=[], + finalbody=[])], + orelse=[])], + decorator_list=[], + returns=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Any', ctx=Load()), + ctx=Load())), + FunctionDef( + name='download', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Fetch chunks of blocks from the RPC provider.\n ')), + Assign( + targets=[ + Name(id='running', ctx=Store())], + value=Constant(value=True)), + While( + test=Name(id='running', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='max', ctx=Load()), + args=[ + Constant(value=1), + BinOp( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='queue', + ctx=Load()), + attr='maxsize', + ctx=Load()), + op=FloorDiv(), + right=Constant(value=2))], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='replies', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='fetch_blocks', + ctx=Load()), + args=[ + BinOp( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[])), + Name(id='count', ctx=Load())], + keywords=[])), + For( + target=Name(id='reply', ctx=Store()), + iter=Name(id='replies', ctx=Load()), + body=[ + AnnAssign( + target=Name(id='to_push', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='bytes', ctx=Load()), + ctx=Load()), + simple=1), + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='reply', ctx=Load()), + Name(id='RpcError', ctx=Load())], + keywords=[]), + body=[ + If( + test=Compare( + left=Attribute( + value=Name(id='reply', ctx=Load()), + attr='code', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + UnaryOp( + op=USub(), + operand=Constant(value=32000))]), + body=[ + Raise( + exc=Name(id='reply', ctx=Load()))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='logging', ctx=Load()), + attr='info', + ctx=Load()), + args=[ + Constant(value='reached end of chain')], + keywords=[ + keyword( + arg='exc_info', + value=Name(id='reply', ctx=Load()))])), + Assign( + targets=[ + Name(id='running', ctx=Store())], + value=Constant(value=False)), + Assign( + targets=[ + Name(id='to_push', ctx=Store())], + value=Constant(value=None))], + orelse=[ + Assign( + targets=[ + Name(id='to_push', ctx=Store())], + value=Name(id='reply', ctx=Load()))]), + While( + test=Constant(value=True), + body=[ + Try( + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='queue', + ctx=Load()), + attr='put', + ctx=Load()), + args=[ + Name(id='to_push', ctx=Load())], + keywords=[ + keyword( + arg='timeout', + value=Constant(value=1))])), + Break()], + handlers=[ + ExceptHandler( + type=Name(id='Full', ctx=Load()), + body=[ + Pass()])], + orelse=[], + finalbody=[])], + orelse=[])], + orelse=[])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='fetch_blocks', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='first', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='count', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Fetch the block specified by the given number from the RPC provider.\n ')), + If( + test=Attribute( + value=Name(id='self', ctx=Load()), + attr='geth', + ctx=Load()), + body=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='fetch_blocks_debug', + ctx=Load()), + args=[ + Name(id='first', ctx=Load()), + Name(id='count', ctx=Load())], + keywords=[]))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='fetch_blocks_eth', + ctx=Load()), + args=[ + Name(id='first', ctx=Load()), + Name(id='count', ctx=Load())], + keywords=[]))])], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Any', ctx=Load()), + Name(id='RpcError', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())), + FunctionDef( + name='fetch_blocks_debug', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='first', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='count', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Fetch the block specified by the given number from the RPC provider as\n an RLP encoded byte array.\n ')), + If( + test=Compare( + left=Name(id='count', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='calls', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='number', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='first', ctx=Load()), + BinOp( + left=Name(id='first', ctx=Load()), + op=Add(), + right=Name(id='count', ctx=Load()))], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='calls', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict( + keys=[ + Constant(value='jsonrpc'), + Constant(value='id'), + Constant(value='method'), + Constant(value='params')], + values=[ + Constant(value='2.0'), + Call( + func=Name(id='hex', ctx=Load()), + args=[ + Name(id='number', ctx=Load())], + keywords=[]), + Constant(value='debug_getRawBlock'), + List( + elts=[ + Call( + func=Name(id='hex', ctx=Load()), + args=[ + Name(id='number', ctx=Load())], + keywords=[])], + ctx=Load())])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dumps', + ctx=Load()), + args=[ + Name(id='calls', ctx=Load())], + keywords=[]), + attr='encode', + ctx=Load()), + args=[ + Constant(value='utf-8')], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='debug', + ctx=Load()), + args=[ + Constant(value='fetching blocks [%d, %d)...'), + Name(id='first', ctx=Load()), + BinOp( + left=Name(id='first', ctx=Load()), + op=Add(), + right=Name(id='count', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='post', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='request', ctx=Load()), + attr='Request', + ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='rpc_url', + ctx=Load())], + keywords=[ + keyword( + arg='data', + value=Name(id='data', ctx=Load())), + keyword( + arg='headers', + value=Dict( + keys=[ + Constant(value='Content-Length'), + Constant(value='Content-Type'), + Constant(value='User-Agent')], + values=[ + Call( + func=Name(id='str', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[]), + Constant(value='application/json'), + Constant(value='ethereum-spec-sync')]))])), + With( + items=[ + withitem( + context_expr=Call( + func=Attribute( + value=Name(id='request', ctx=Load()), + attr='urlopen', + ctx=Load()), + args=[ + Name(id='post', ctx=Load())], + keywords=[]), + optional_vars=Name(id='response', ctx=Store()))], + body=[ + Assign( + targets=[ + Name(id='replies', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='response', ctx=Load())], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='replies', ctx=Load()), + Name(id='list', ctx=Load())], + keywords=[])), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='error', + ctx=Load()), + args=[ + Constant(value='got non-list JSON-RPC response. replies=%r'), + Name(id='replies', ctx=Load())], + keywords=[])), + Raise( + exc=Name(id='ValueError', ctx=Load()))], + orelse=[]), + AnnAssign( + target=Name(id='block_rlps', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='RpcError', ctx=Load()), + Name(id='bytes', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Name(id='reply', ctx=Store()), + iter=Name(id='replies', ctx=Load()), + body=[ + Try( + body=[ + Assign( + targets=[ + Name(id='reply_id', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Subscript( + value=Name(id='reply', ctx=Load()), + slice=Constant(value='id'), + ctx=Load()), + Constant(value=0)], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='Exception', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='exception', + ctx=Load()), + args=[ + Constant(value='unable to parse RPC id. reply=%r'), + Name(id='reply', ctx=Load())], + keywords=[])), + Raise()])], + orelse=[], + finalbody=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='reply_id', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='first', ctx=Load())]), + Compare( + left=Name(id='reply_id', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='first', ctx=Load()), + op=Add(), + right=Name(id='count', ctx=Load()))])]), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value='mismatched request id')], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Constant(value='error'), + ops=[ + In()], + comparators=[ + Name(id='reply', ctx=Load())]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='block_rlps', ctx=Load()), + slice=Name(id='reply_id', ctx=Load()), + ctx=Store())], + value=Call( + func=Name(id='RpcError', ctx=Load()), + args=[ + Subscript( + value=Subscript( + value=Name(id='reply', ctx=Load()), + slice=Constant(value='error'), + ctx=Load()), + slice=Constant(value='code'), + ctx=Load()), + Subscript( + value=Subscript( + value=Name(id='reply', ctx=Load()), + slice=Constant(value='error'), + ctx=Load()), + slice=Constant(value='message'), + ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Name(id='block_rlps', ctx=Load()), + slice=Name(id='reply_id', ctx=Load()), + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='bytes', ctx=Load()), + attr='fromhex', + ctx=Load()), + args=[ + Subscript( + value=Subscript( + value=Name(id='reply', ctx=Load()), + slice=Constant(value='result'), + ctx=Load()), + slice=Slice( + lower=Constant(value=2)), + ctx=Load())], + keywords=[]))])], + orelse=[]), + If( + test=Compare( + left=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='block_rlps', ctx=Load())], + keywords=[]), + ops=[ + NotEq()], + comparators=[ + Name(id='count', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='expected '), + FormattedValue( + value=Name(id='count', ctx=Load()), + conversion=-1), + Constant(value=' blocks but only got '), + FormattedValue( + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='block_rlps', ctx=Load())], + keywords=[]), + conversion=-1)])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='info', + ctx=Load()), + args=[ + Constant(value='blocks [%d, %d) fetched'), + Name(id='first', ctx=Load()), + BinOp( + left=Name(id='first', ctx=Load()), + op=Add(), + right=Name(id='count', ctx=Load()))], + keywords=[])), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='RpcError', ctx=Load()), + Name(id='Any', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load()), + value=List(elts=[], ctx=Load()), + simple=1), + For( + target=Tuple( + elts=[ + Name(id='_', ctx=Store()), + Name(id='block_rlp', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='sorted', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='block_rlps', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + body=[ + If( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='block_rlp', ctx=Load()), + Name(id='RpcError', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='block_rlp', ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='decoded_block', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode', + ctx=Load()), + args=[ + Name(id='block_rlp', ctx=Load())], + keywords=[])), + Assert( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Name(id='decoded_block', ctx=Load()), + Name(id='bytes', ctx=Load())], + keywords=[]))), + Assert( + test=UnaryOp( + op=Not(), + operand=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Name(id='decoded_block', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + Name(id='bytes', ctx=Load())], + keywords=[]))), + Assert( + test=Call( + func=Name(id='isinstance', ctx=Load()), + args=[ + Subscript( + value=Subscript( + value=Name(id='decoded_block', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + slice=Constant(value=11), + ctx=Load()), + Name(id='bytes', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='timestamp', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='U256', ctx=Load()), + attr='from_be_bytes', + ctx=Load()), + args=[ + Subscript( + value=Subscript( + value=Name(id='decoded_block', ctx=Load()), + slice=Constant(value=0), + ctx=Load()), + slice=Constant(value=11), + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='advance_block', + ctx=Load()), + args=[ + Name(id='timestamp', ctx=Load())], + keywords=[])), + Try( + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='decode_to', + ctx=Load()), + args=[ + Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='blocks')], + keywords=[]), + attr='Block', + ctx=Load()), + Name(id='block_rlp', ctx=Load())], + keywords=[])], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='Exception', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='exception', + ctx=Load()), + args=[ + Constant(value='failed to decode block %d with timestamp %d'), + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load()), + Name(id='timestamp', ctx=Load())], + keywords=[])), + Raise()])], + orelse=[], + finalbody=[])])], + orelse=[]), + Return( + value=Name(id='blocks', ctx=Load()))])], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='bytes', ctx=Load()), + Name(id='RpcError', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())), + FunctionDef( + name='load_transaction', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='t', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Turn a json transaction into a `Transaction`.\n ')), + Assign( + targets=[ + Name(id='access_list', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='sublist', ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='t', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='accessList'), + List(elts=[], ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='access_list', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Tuple( + elts=[ + Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='utils.hexadecimal')], + keywords=[]), + attr='hex_to_address', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='sublist', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='address')], + keywords=[])], + keywords=[]), + ListComp( + elt=Call( + func=Name(id='hex_to_bytes32', ctx=Load()), + args=[ + Name(id='key', ctx=Load())], + keywords=[]), + generators=[ + comprehension( + target=Name(id='key', ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='sublist', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='storageKeys')], + keywords=[]), + ifs=[], + is_async=0)])], + ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Call( + func=Name(id='hasattr', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='transactions')], + keywords=[]), + Constant(value='LegacyTransaction')], + keywords=[]), + body=[ + If( + test=Compare( + left=Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='type'), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='0x1')]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x01'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='transactions')], + keywords=[]), + attr='AccessListTransaction', + ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_u64', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='chainId'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='nonce'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='gasPrice'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='gas'), + ctx=Load())], + keywords=[]), + IfExp( + test=Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='to'), + ctx=Load()), + body=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='utils.hexadecimal')], + keywords=[]), + attr='hex_to_address', + ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='to'), + ctx=Load())], + keywords=[]), + orelse=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='value'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='input'), + ctx=Load())], + keywords=[]), + Name(id='access_list', ctx=Load()), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='v'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='r'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='s'), + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])))], + orelse=[ + If( + test=Compare( + left=Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='type'), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='0x2')]), + body=[ + Return( + value=BinOp( + left=Constant(value=b'\x02'), + op=Add(), + right=Call( + func=Attribute( + value=Name(id='rlp', ctx=Load()), + attr='encode', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='transactions')], + keywords=[]), + attr='FeeMarketTransaction', + ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_u64', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='chainId'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='nonce'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='maxPriorityFeePerGas'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='maxFeePerGas'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='gas'), + ctx=Load())], + keywords=[]), + IfExp( + test=Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='to'), + ctx=Load()), + body=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='utils.hexadecimal')], + keywords=[]), + attr='hex_to_address', + ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='to'), + ctx=Load())], + keywords=[]), + orelse=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='value'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='input'), + ctx=Load())], + keywords=[]), + Name(id='access_list', ctx=Load()), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='v'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='r'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='s'), + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[])))], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='transactions')], + keywords=[]), + attr='LegacyTransaction', + ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='nonce'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='gasPrice'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='gas'), + ctx=Load())], + keywords=[]), + IfExp( + test=Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='to'), + ctx=Load()), + body=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='utils.hexadecimal')], + keywords=[]), + attr='hex_to_address', + ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='to'), + ctx=Load())], + keywords=[]), + orelse=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='value'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='input'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='v'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='r'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='s'), + ctx=Load())], + keywords=[])], + keywords=[]))])])], + orelse=[ + Return( + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='transactions')], + keywords=[]), + attr='Transaction', + ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='nonce'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='gasPrice'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='gas'), + ctx=Load())], + keywords=[]), + IfExp( + test=Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='to'), + ctx=Load()), + body=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='utils.hexadecimal')], + keywords=[]), + attr='hex_to_address', + ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='to'), + ctx=Load())], + keywords=[]), + orelse=Call( + func=Name(id='Bytes0', ctx=Load()), + args=[ + Constant(value=b'')], + keywords=[])), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='value'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='input'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='v'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='r'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='t', ctx=Load()), + slice=Constant(value='s'), + ctx=Load())], + keywords=[])], + keywords=[]))])], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='fetch_blocks_eth', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='first', + annotation=Name(id='Uint', ctx=Load())), + arg( + arg='count', + annotation=Name(id='Uint', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Fetch the block specified by the given number from the RPC provider\n using only standard endpoints.\n ')), + If( + test=Compare( + left=Name(id='count', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Return( + value=List(elts=[], ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='calls', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='number', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='first', ctx=Load()), + BinOp( + left=Name(id='first', ctx=Load()), + op=Add(), + right=Name(id='count', ctx=Load()))], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='calls', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict( + keys=[ + Constant(value='jsonrpc'), + Constant(value='id'), + Constant(value='method'), + Constant(value='params')], + values=[ + Constant(value='2.0'), + Call( + func=Name(id='hex', ctx=Load()), + args=[ + Name(id='number', ctx=Load())], + keywords=[]), + Constant(value='eth_getBlockByNumber'), + List( + elts=[ + Call( + func=Name(id='hex', ctx=Load()), + args=[ + Name(id='number', ctx=Load())], + keywords=[]), + Constant(value=True)], + ctx=Load())])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dumps', + ctx=Load()), + args=[ + Name(id='calls', ctx=Load())], + keywords=[]), + attr='encode', + ctx=Load()), + args=[ + Constant(value='utf-8')], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='debug', + ctx=Load()), + args=[ + Constant(value='fetching blocks [%d, %d)...'), + Name(id='first', ctx=Load()), + BinOp( + left=Name(id='first', ctx=Load()), + op=Add(), + right=Name(id='count', ctx=Load()))], + keywords=[])), + Assign( + targets=[ + Name(id='post', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='request', ctx=Load()), + attr='Request', + ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='rpc_url', + ctx=Load())], + keywords=[ + keyword( + arg='data', + value=Name(id='data', ctx=Load())), + keyword( + arg='headers', + value=Dict( + keys=[ + Constant(value='Content-Length'), + Constant(value='Content-Type'), + Constant(value='User-Agent')], + values=[ + Call( + func=Name(id='str', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[]), + Constant(value='application/json'), + Constant(value='ethereum-spec-sync')]))])), + With( + items=[ + withitem( + context_expr=Call( + func=Attribute( + value=Name(id='request', ctx=Load()), + attr='urlopen', + ctx=Load()), + args=[ + Name(id='post', ctx=Load())], + keywords=[]), + optional_vars=Name(id='response', ctx=Store()))], + body=[ + Assign( + targets=[ + Name(id='replies', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='response', ctx=Load())], + keywords=[])), + AnnAssign( + target=Name(id='block_jsons', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='Any', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + AnnAssign( + target=Name(id='ommers_needed', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='int', ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + AnnAssign( + target=Name(id='blocks', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Any', ctx=Load()), + Name(id='RpcError', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + For( + target=Name(id='reply', ctx=Store()), + iter=Name(id='replies', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='reply_id', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Subscript( + value=Name(id='reply', ctx=Load()), + slice=Constant(value='id'), + ctx=Load()), + Constant(value=0)], + keywords=[])], + keywords=[])), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='reply_id', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Name(id='first', ctx=Load())]), + Compare( + left=Name(id='reply_id', ctx=Load()), + ops=[ + GtE()], + comparators=[ + BinOp( + left=Name(id='first', ctx=Load()), + op=Add(), + right=Name(id='count', ctx=Load()))])]), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + Constant(value='mismatched request id')], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Constant(value='error'), + ops=[ + In()], + comparators=[ + Name(id='reply', ctx=Load())]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='blocks', ctx=Load()), + slice=Name(id='reply_id', ctx=Load()), + ctx=Store())], + value=Call( + func=Name(id='RpcError', ctx=Load()), + args=[ + Subscript( + value=Subscript( + value=Name(id='reply', ctx=Load()), + slice=Constant(value='error'), + ctx=Load()), + slice=Constant(value='code'), + ctx=Load()), + Subscript( + value=Subscript( + value=Name(id='reply', ctx=Load()), + slice=Constant(value='error'), + ctx=Load()), + slice=Constant(value='message'), + ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='res', ctx=Store())], + value=Subscript( + value=Name(id='reply', ctx=Load()), + slice=Constant(value='result'), + ctx=Load())), + If( + test=Compare( + left=Name(id='res', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + ImportFrom( + module='time', + names=[ + alias(name='sleep')], + level=0), + Expr( + value=Call( + func=Name(id='sleep', ctx=Load()), + args=[ + Constant(value=12)], + keywords=[])), + Break()], + orelse=[]), + Assign( + targets=[ + Subscript( + value=Name(id='block_jsons', ctx=Load()), + slice=Name(id='reply_id', ctx=Load()), + ctx=Store())], + value=Name(id='res', ctx=Load())), + Assign( + targets=[ + Subscript( + value=Name(id='ommers_needed', ctx=Load()), + slice=Name(id='reply_id', ctx=Load()), + ctx=Store())], + value=Call( + func=Name(id='len', ctx=Load()), + args=[ + Subscript( + value=Name(id='res', ctx=Load()), + slice=Constant(value='uncles'), + ctx=Load())], + keywords=[]))])], + orelse=[]), + Assign( + targets=[ + Name(id='ommers', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='fetch_ommers', + ctx=Load()), + args=[ + Name(id='ommers_needed', ctx=Load())], + keywords=[])), + For( + target=Name(id='id', ctx=Store()), + iter=Name(id='block_jsons', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='advance_block', + ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Subscript( + value=Name(id='block_jsons', ctx=Load()), + slice=Name(id='id', ctx=Load()), + ctx=Load()), + slice=Constant(value='timestamp'), + ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Subscript( + value=Name(id='blocks', ctx=Load()), + slice=Name(id='id', ctx=Load()), + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='make_block', + ctx=Load()), + args=[ + Subscript( + value=Name(id='block_jsons', ctx=Load()), + slice=Name(id='id', ctx=Load()), + ctx=Load()), + Call( + func=Attribute( + value=Name(id='ommers', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Name(id='id', ctx=Load()), + Tuple(elts=[], ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='info', + ctx=Load()), + args=[ + Constant(value='blocks [%d, %d) fetched'), + Name(id='first', ctx=Load()), + BinOp( + left=Name(id='first', ctx=Load()), + op=Add(), + right=Name(id='count', ctx=Load()))], + keywords=[])), + Return( + value=ListComp( + elt=Name(id='v', ctx=Load()), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='_', ctx=Store()), + Name(id='v', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='sorted', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + ifs=[], + is_async=0)]))])], + decorator_list=[], + returns=Subscript( + value=Name(id='List', ctx=Load()), + slice=Subscript( + value=Name(id='Union', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Any', ctx=Load()), + Name(id='RpcError', ctx=Load())], + ctx=Load()), + ctx=Load()), + ctx=Load())), + FunctionDef( + name='fetch_ommers', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='ommers_needed', + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='int', ctx=Load())], + ctx=Load()), + ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Fetch the ommers for a given block from the RPC provider.\n ')), + Assign( + targets=[ + Name(id='calls', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Tuple( + elts=[ + Name(id='block_number', ctx=Store()), + Name(id='num_ommers', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='ommers_needed', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + body=[ + For( + target=Name(id='i', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='num_ommers', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='calls', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Dict( + keys=[ + Constant(value='jsonrpc'), + Constant(value='id'), + Constant(value='method'), + Constant(value='params')], + values=[ + Constant(value='2.0'), + Call( + func=Name(id='hex', ctx=Load()), + args=[ + BinOp( + left=BinOp( + left=Name(id='block_number', ctx=Load()), + op=Mult(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[]))], + keywords=[]), + Constant(value='eth_getUncleByBlockNumberAndIndex'), + List( + elts=[ + Call( + func=Name(id='hex', ctx=Load()), + args=[ + Name(id='block_number', ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex', ctx=Load()), + args=[ + Name(id='i', ctx=Load())], + keywords=[])], + ctx=Load())])], + keywords=[]))], + orelse=[])], + orelse=[]), + If( + test=Compare( + left=Name(id='calls', ctx=Load()), + ops=[ + Eq()], + comparators=[ + List(elts=[], ctx=Load())]), + body=[ + Return( + value=Dict(keys=[], values=[]))], + orelse=[]), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dumps', + ctx=Load()), + args=[ + Name(id='calls', ctx=Load())], + keywords=[]), + attr='encode', + ctx=Load()), + args=[ + Constant(value='utf-8')], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='debug', + ctx=Load()), + args=[ + Constant(value='fetching ommers [%d, %d]...'), + Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='ommers_needed', ctx=Load())], + keywords=[]), + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='ommers_needed', ctx=Load())], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='post', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='request', ctx=Load()), + attr='Request', + ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='rpc_url', + ctx=Load())], + keywords=[ + keyword( + arg='data', + value=Name(id='data', ctx=Load())), + keyword( + arg='headers', + value=Dict( + keys=[ + Constant(value='Content-Length'), + Constant(value='Content-Type'), + Constant(value='User-Agent')], + values=[ + Call( + func=Name(id='str', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[]), + Constant(value='application/json'), + Constant(value='ethereum-spec-sync')]))])), + With( + items=[ + withitem( + context_expr=Call( + func=Attribute( + value=Name(id='request', ctx=Load()), + attr='urlopen', + ctx=Load()), + args=[ + Name(id='post', ctx=Load())], + keywords=[]), + optional_vars=Name(id='response', ctx=Store()))], + body=[ + Assign( + targets=[ + Name(id='replies', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='response', ctx=Load())], + keywords=[])), + AnnAssign( + target=Name(id='ommers', ctx=Store()), + annotation=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='Any', ctx=Load())], + ctx=Load()), + ctx=Load())], + ctx=Load()), + ctx=Load()), + value=Dict(keys=[], values=[]), + simple=1), + Assign( + targets=[ + Name(id='twenty', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=20)], + keywords=[])), + For( + target=Name(id='reply', ctx=Store()), + iter=Name(id='replies', ctx=Load()), + body=[ + Assign( + targets=[ + Name(id='reply_id', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Subscript( + value=Name(id='reply', ctx=Load()), + slice=Constant(value='id'), + ctx=Load()), + Constant(value=0)], + keywords=[])], + keywords=[])), + If( + test=Compare( + left=BinOp( + left=Name(id='reply_id', ctx=Load()), + op=FloorDiv(), + right=Name(id='twenty', ctx=Load())), + ops=[ + NotIn()], + comparators=[ + Name(id='ommers', ctx=Load())]), + body=[ + Assign( + targets=[ + Subscript( + value=Name(id='ommers', ctx=Load()), + slice=BinOp( + left=Name(id='reply_id', ctx=Load()), + op=FloorDiv(), + right=Name(id='twenty', ctx=Load())), + ctx=Store())], + value=Dict(keys=[], values=[]))], + orelse=[]), + If( + test=Compare( + left=Constant(value='error'), + ops=[ + In()], + comparators=[ + Name(id='reply', ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='RpcError', ctx=Load()), + args=[ + Subscript( + value=Subscript( + value=Name(id='reply', ctx=Load()), + slice=Constant(value='error'), + ctx=Load()), + slice=Constant(value='code'), + ctx=Load()), + Subscript( + value=Subscript( + value=Name(id='reply', ctx=Load()), + slice=Constant(value='error'), + ctx=Load()), + slice=Constant(value='message'), + ctx=Load())], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Subscript( + value=Subscript( + value=Name(id='ommers', ctx=Load()), + slice=BinOp( + left=Name(id='reply_id', ctx=Load()), + op=FloorDiv(), + right=Name(id='twenty', ctx=Load())), + ctx=Load()), + slice=BinOp( + left=Name(id='reply_id', ctx=Load()), + op=Mod(), + right=Name(id='twenty', ctx=Load())), + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='make_header', + ctx=Load()), + args=[ + Subscript( + value=Name(id='reply', ctx=Load()), + slice=Constant(value='result'), + ctx=Load())], + keywords=[]))])], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='info', + ctx=Load()), + args=[ + Constant(value='ommers [%d, %d] fetched'), + Call( + func=Name(id='min', ctx=Load()), + args=[ + Name(id='ommers_needed', ctx=Load())], + keywords=[]), + Call( + func=Name(id='max', ctx=Load()), + args=[ + Name(id='ommers_needed', ctx=Load())], + keywords=[])], + keywords=[])), + Return( + value=DictComp( + key=Name(id='k', ctx=Load()), + value=Call( + func=Name(id='tuple', ctx=Load()), + args=[ + GeneratorExp( + elt=Name(id='x', ctx=Load()), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='_', ctx=Store()), + Name(id='x', ctx=Store())], + ctx=Store()), + iter=Call( + func=Name(id='sorted', ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='v', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]), + ifs=[], + is_async=0)])], + keywords=[]), + generators=[ + comprehension( + target=Tuple( + elts=[ + Name(id='k', ctx=Store()), + Name(id='v', ctx=Store())], + ctx=Store()), + iter=Call( + func=Attribute( + value=Name(id='ommers', ctx=Load()), + attr='items', + ctx=Load()), + args=[], + keywords=[]), + ifs=[], + is_async=0)]))])], + decorator_list=[], + returns=Subscript( + value=Name(id='Dict', ctx=Load()), + slice=Tuple( + elts=[ + Name(id='Uint', ctx=Load()), + Name(id='Any', ctx=Load())], + ctx=Load()), + ctx=Load())), + FunctionDef( + name='make_header', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='json', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a Header object from JSON describing it.\n ')), + Assign( + targets=[ + Name(id='fields', ctx=Store())], + value=List( + elts=[ + Call( + func=Name(id='hex_to_bytes32', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='parentHash'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_bytes32', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='sha3Uncles'), + ctx=Load())], + keywords=[]), + Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='utils.hexadecimal')], + keywords=[]), + attr='hex_to_address', + ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='miner'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_bytes32', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='stateRoot'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_bytes32', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='transactionsRoot'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_bytes32', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='receiptsRoot'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='Bytes256', ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='logsBloom'), + ctx=Load())], + keywords=[])], + keywords=[]), + Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='difficulty'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='number'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='gasLimit'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='gasUsed'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='timestamp'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_bytes', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='extraData'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_bytes32', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='mixHash'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_bytes8', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='nonce'), + ctx=Load())], + keywords=[])], + ctx=Load())), + If( + test=Call( + func=Name(id='hasattr', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='blocks')], + keywords=[]), + attr='Header', + ctx=Load()), + Constant(value='base_fee_per_gas')], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='fields', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_uint', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='baseFeePerGas'), + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[]), + If( + test=Call( + func=Name(id='hasattr', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='blocks')], + keywords=[]), + attr='Header', + ctx=Load()), + Constant(value='withdrawals_root')], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='fields', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_bytes32', ctx=Load()), + args=[ + Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='withdrawalsRoot'), + ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='blocks')], + keywords=[]), + attr='Header', + ctx=Load()), + args=[ + Starred( + value=Name(id='fields', ctx=Load()), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='make_block', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='json', + annotation=Name(id='Any', ctx=Load())), + arg( + arg='ommers', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Create a block from JSON describing it.\n ')), + Assign( + targets=[ + Name(id='header', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='make_header', + ctx=Load()), + args=[ + Name(id='json', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='transactions', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='t', ctx=Store()), + iter=Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='transactions'), + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='transactions', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='load_transaction', + ctx=Load()), + args=[ + Name(id='t', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='get', + ctx=Load()), + args=[ + Constant(value='withdrawals')], + keywords=[]), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='withdrawals', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='j', ctx=Store()), + iter=Subscript( + value=Name(id='json', ctx=Load()), + slice=Constant(value='withdrawals'), + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='withdrawals', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='blocks')], + keywords=[]), + attr='Withdrawal', + ctx=Load()), + args=[ + Call( + func=Name(id='hex_to_u64', ctx=Load()), + args=[ + Subscript( + value=Name(id='j', ctx=Load()), + slice=Constant(value='index'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u64', ctx=Load()), + args=[ + Subscript( + value=Name(id='j', ctx=Load()), + slice=Constant(value='validatorIndex'), + ctx=Load())], + keywords=[]), + Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='utils.hexadecimal')], + keywords=[]), + attr='hex_to_address', + ctx=Load()), + args=[ + Subscript( + value=Name(id='j', ctx=Load()), + slice=Constant(value='address'), + ctx=Load())], + keywords=[]), + Call( + func=Name(id='hex_to_u256', ctx=Load()), + args=[ + Subscript( + value=Name(id='j', ctx=Load()), + slice=Constant(value='amount'), + ctx=Load())], + keywords=[])], + keywords=[])], + keywords=[]))], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Name(id='extra_fields', ctx=Store())], + value=List(elts=[], ctx=Load())), + If( + test=Call( + func=Name(id='hasattr', ctx=Load()), + args=[ + Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='blocks')], + keywords=[]), + attr='Block', + ctx=Load()), + Constant(value='withdrawals')], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='extra_fields', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Name(id='withdrawals', ctx=Load())], + keywords=[]))], + orelse=[]), + Return( + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='blocks')], + keywords=[]), + attr='Block', + ctx=Load()), + args=[ + Name(id='header', ctx=Load()), + Call( + func=Name(id='tuple', ctx=Load()), + args=[ + Name(id='transactions', ctx=Load())], + keywords=[]), + Name(id='ommers', ctx=Load()), + Starred( + value=Name(id='extra_fields', ctx=Load()), + ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Name(id='Any', ctx=Load())), + FunctionDef( + name='download_chain_id', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Fetch the chain id of the executing chain from the rpc provider.\n ')), + Assign( + targets=[ + Name(id='call', ctx=Store())], + value=List( + elts=[ + Dict( + keys=[ + Constant(value='jsonrpc'), + Constant(value='id'), + Constant(value='method'), + Constant(value='params')], + values=[ + Constant(value='2.0'), + Call( + func=Name(id='hex', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[]), + Constant(value='eth_chainId'), + List(elts=[], ctx=Load())])], + ctx=Load())), + Assign( + targets=[ + Name(id='data', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='dumps', + ctx=Load()), + args=[ + Name(id='call', ctx=Load())], + keywords=[]), + attr='encode', + ctx=Load()), + args=[ + Constant(value='utf-8')], + keywords=[])), + Assign( + targets=[ + Name(id='post', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='request', ctx=Load()), + attr='Request', + ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='rpc_url', + ctx=Load())], + keywords=[ + keyword( + arg='data', + value=Name(id='data', ctx=Load())), + keyword( + arg='headers', + value=Dict( + keys=[ + Constant(value='Content-Length'), + Constant(value='Content-Type'), + Constant(value='User-Agent')], + values=[ + Call( + func=Name(id='str', ctx=Load()), + args=[ + Call( + func=Name(id='len', ctx=Load()), + args=[ + Name(id='data', ctx=Load())], + keywords=[])], + keywords=[]), + Constant(value='application/json'), + Constant(value='ethereum-spec-sync')]))])), + With( + items=[ + withitem( + context_expr=Call( + func=Attribute( + value=Name(id='request', ctx=Load()), + attr='urlopen', + ctx=Load()), + args=[ + Name(id='post', ctx=Load())], + keywords=[]), + optional_vars=Name(id='response', ctx=Store()))], + body=[ + Assign( + targets=[ + Name(id='reply', ctx=Store())], + value=Subscript( + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='load', + ctx=Load()), + args=[ + Name(id='response', ctx=Load())], + keywords=[]), + slice=Constant(value=0), + ctx=Load())), + Assert( + test=Compare( + left=Subscript( + value=Name(id='reply', ctx=Load()), + slice=Constant(value='id'), + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Call( + func=Name(id='hex', ctx=Load()), + args=[ + Constant(value=2)], + keywords=[])])), + Assign( + targets=[ + Name(id='chain_id', ctx=Store())], + value=Call( + func=Name(id='U64', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Subscript( + value=Name(id='reply', ctx=Load()), + slice=Constant(value='result'), + ctx=Load()), + Constant(value=16)], + keywords=[])], + keywords=[]))]), + Return( + value=Name(id='chain_id', ctx=Load()))], + decorator_list=[], + returns=Name(id='U64', ctx=Load()))], + decorator_list=[]), + ClassDef( + name='Sync', + bases=[ + Name(id='ForkTracking', ctx=Load())], + keywords=[], + body=[ + Expr( + value=Constant(value='\n A command line tool to fetch blocks from an RPC provider and validate them\n against the specification.\n ')), + FunctionDef( + name='parse_arguments', + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Parse command line arguments.\n ')), + Assign( + targets=[ + Name(id='parser', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='ArgumentParser', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--rpc-url')], + keywords=[ + keyword( + arg='help', + value=Constant(value='endpoint providing the Ethereum RPC API')), + keyword( + arg='default', + value=Constant(value='http://localhost:8545/'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--unoptimized')], + keywords=[ + keyword( + arg='help', + value=Constant(value="don't use the optimized state/ethash (extremely slow)")), + keyword( + arg='action', + value=Constant(value='store_true'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--persist')], + keywords=[ + keyword( + arg='help', + value=Constant(value='store the state in a db in this file'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--geth')], + keywords=[ + keyword( + arg='help', + value=Constant(value='use geth specific RPC endpoints while fetching blocks')), + keyword( + arg='action', + value=Constant(value='store_true'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--reset')], + keywords=[ + keyword( + arg='help', + value=Constant(value='delete the db and start from scratch')), + keyword( + arg='action', + value=Constant(value='store_true'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--gas-per-commit')], + keywords=[ + keyword( + arg='help', + value=Constant(value='commit to db each time this much gas is consumed')), + keyword( + arg='type', + value=Name(id='int', ctx=Load())), + keyword( + arg='default', + value=Constant(value=1000000000))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--initial-state')], + keywords=[ + keyword( + arg='help', + value=Constant(value='start from the state in this db, rather than genesis'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--stop-at')], + keywords=[ + keyword( + arg='help', + value=Constant(value='after syncing this block, exit successfully')), + keyword( + arg='type', + value=Name(id='int', ctx=Load()))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--mainnet')], + keywords=[ + keyword( + arg='help', + value=Constant(value='Set the chain to mainnet')), + keyword( + arg='action', + value=Constant(value='store_const')), + keyword( + arg='dest', + value=Constant(value='chain')), + keyword( + arg='const', + value=Constant(value='mainnet')), + keyword( + arg='default', + value=Constant(value='mainnet'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--zhejiang')], + keywords=[ + keyword( + arg='help', + value=Constant(value='Set the chain to mainnet')), + keyword( + arg='action', + value=Constant(value='store_const')), + keyword( + arg='dest', + value=Constant(value='chain')), + keyword( + arg='const', + value=Constant(value='zhejiang'))])), + Expr( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='add_argument', + ctx=Load()), + args=[ + Constant(value='--sepolia')], + keywords=[ + keyword( + arg='help', + value=Constant(value='Set the chain to mainnet')), + keyword( + arg='action', + value=Constant(value='store_const')), + keyword( + arg='dest', + value=Constant(value='chain')), + keyword( + arg='const', + value=Constant(value='sepolia'))])), + Return( + value=Call( + func=Attribute( + value=Name(id='parser', ctx=Load()), + attr='parse_args', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[ + Name(id='staticmethod', ctx=Load())], + returns=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='Namespace', + ctx=Load())), + AnnAssign( + target=Name(id='downloader', ctx=Store()), + annotation=Name(id='BlockDownloader', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='options', ctx=Store()), + annotation=Attribute( + value=Name(id='argparse', ctx=Load()), + attr='Namespace', + ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='chain', ctx=Store()), + annotation=Name(id='Any', ctx=Load()), + simple=1), + AnnAssign( + target=Name(id='log', ctx=Store()), + annotation=Attribute( + value=Name(id='logging', ctx=Load()), + attr='Logger', + ctx=Load()), + simple=1), + FunctionDef( + name='__init__', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='logging', ctx=Load()), + attr='getLogger', + ctx=Load()), + args=[ + Name(id='__name__', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='parse_arguments', + ctx=Load()), + args=[], + keywords=[])), + If( + test=UnaryOp( + op=Not(), + operand=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='unoptimized', + ctx=Load())), + body=[ + Import( + names=[ + alias(name='ethereum_optimized')]), + Expr( + value=Call( + func=Attribute( + value=Name(id='ethereum_optimized', ctx=Load()), + attr='monkey_patch', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='state_path', + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='persist', + ctx=Load()))]))], + orelse=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='persist', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='error', + ctx=Load()), + args=[ + Constant(value='--persist is not supported with --unoptimized')], + keywords=[])), + Expr( + value=Call( + func=Name(id='exit', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='initial_state', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='error', + ctx=Load()), + args=[ + Constant(value='--initial-state is not supported with --unoptimized')], + keywords=[])), + Expr( + value=Call( + func=Name(id='exit', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + If( + test=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='reset', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='error', + ctx=Load()), + args=[ + Constant(value='--reset is not supported with --unoptimized')], + keywords=[])), + Expr( + value=Call( + func=Name(id='exit', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[])]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='persist', + ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='initial_state', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='error', + ctx=Load()), + args=[ + Constant(value='--initial_state is not supported without --persist')], + keywords=[])), + Expr( + value=Call( + func=Name(id='exit', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[]), + If( + test=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='reset', + ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='error', + ctx=Load()), + args=[ + Constant(value='--reset is not supported without --persist')], + keywords=[])), + Expr( + value=Call( + func=Name(id='exit', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Name(id='config_str', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Name(id='cast', ctx=Load()), + args=[ + Name(id='bytes', ctx=Load()), + Call( + func=Attribute( + value=Name(id='pkgutil', ctx=Load()), + attr='get_data', + ctx=Load()), + args=[ + Constant(value='ethereum'), + JoinedStr( + values=[ + Constant(value='assets/'), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='chain', + ctx=Load()), + conversion=-1), + Constant(value='.json')])], + keywords=[])], + keywords=[]), + attr='decode', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='config', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='json', ctx=Load()), + attr='loads', + ctx=Load()), + args=[ + Name(id='config_str', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='chain', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='mainnet')]), + body=[ + Assign( + targets=[ + Name(id='forks', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Hardfork', ctx=Load()), + attr='discover', + ctx=Load()), + args=[], + keywords=[]))], + orelse=[ + Assign( + targets=[ + Name(id='forks', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='Hardfork', ctx=Load()), + attr='load_from_json', + ctx=Load()), + args=[ + Name(id='config', ctx=Load())], + keywords=[]))]), + Expr( + value=Call( + func=Attribute( + value=Name(id='ForkTracking', ctx=Load()), + attr='__init__', + ctx=Load()), + args=[ + Name(id='self', ctx=Load()), + Name(id='forks', ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Call( + func=Name(id='U256', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[])], + keywords=[])), + If( + test=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='reset', + ctx=Load()), + body=[ + Import( + names=[ + alias(name='rust_pyspec_glue')]), + Assert( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='persist', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='rust_pyspec_glue', ctx=Load()), + attr='DB', + ctx=Load()), + attr='delete', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='persist', + ctx=Load())], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='initial_state', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assert( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='persist', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)])), + If( + test=UnaryOp( + op=Not(), + operand=Call( + func=Attribute( + value=Attribute( + value=Name(id='os', ctx=Load()), + attr='path', + ctx=Load()), + attr='exists', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='os', ctx=Load()), + attr='path', + ctx=Load()), + attr='join', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='persist', + ctx=Load()), + Constant(value='mdbx.dat')], + keywords=[])], + keywords=[])), + body=[ + Try( + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='os', ctx=Load()), + attr='mkdir', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='persist', + ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='FileExistsError', ctx=Load()), + body=[ + Pass()])], + orelse=[], + finalbody=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='shutil', ctx=Load()), + attr='copy', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='os', ctx=Load()), + attr='path', + ctx=Load()), + attr='join', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='initial_state', + ctx=Load()), + Constant(value='mdbx.dat')], + keywords=[]), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='persist', + ctx=Load())], + keywords=[]))], + orelse=[])], + orelse=[]), + Assign( + targets=[ + Name(id='state', ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='State', + ctx=Load()), + args=[], + keywords=[])), + AnnAssign( + target=Name(id='persisted_block', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Uint', ctx=Load()), + ctx=Load()), + value=Constant(value=None), + simple=1), + AnnAssign( + target=Name(id='persisted_block_timestamp', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='U256', ctx=Load()), + ctx=Load()), + value=Constant(value=None), + simple=1), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='persist', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='state_mod', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[])), + Assign( + targets=[ + Name(id='persisted_block_opt', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='state_mod', ctx=Load()), + attr='get_metadata', + ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Constant(value=b'block_number')], + keywords=[])), + Assign( + targets=[ + Name(id='persisted_block_timestamp_opt', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='state_mod', ctx=Load()), + attr='get_metadata', + ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Constant(value=b'block_timestamp')], + keywords=[])), + If( + test=Compare( + left=Name(id='persisted_block_opt', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='persisted_block', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='persisted_block_opt', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[]), + If( + test=Compare( + left=Name(id='persisted_block_timestamp_opt', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='persisted_block_timestamp', ctx=Store())], + value=Call( + func=Name(id='U256', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='persisted_block_timestamp_opt', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[])], + orelse=[]), + If( + test=BoolOp( + op=Or(), + values=[ + Compare( + left=Name(id='persisted_block', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + Compare( + left=Name(id='persisted_block_timestamp', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)])]), + body=[ + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='BlockChain', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='blocks', + value=List(elts=[], ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='chain_id', + value=Constant(value=None))])), + Assign( + targets=[ + Name(id='genesis_configuration', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='genesis', ctx=Load()), + attr='get_genesis_configuration', + ctx=Load()), + args=[ + JoinedStr( + values=[ + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='chain', + ctx=Load()), + conversion=-1), + Constant(value='.json')])], + keywords=[])), + AnnAssign( + target=Name(id='description', ctx=Store()), + annotation=Attribute( + value=Name(id='genesis', ctx=Load()), + attr='GenesisFork', + ctx=Load()), + value=Call( + func=Attribute( + value=Name(id='genesis', ctx=Load()), + attr='GenesisFork', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='Address', + value=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork', + ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='fork_types')], + keywords=[]), + attr='Address', + ctx=Load())), + keyword( + arg='Account', + value=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork', + ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='fork_types')], + keywords=[]), + attr='Account', + ctx=Load())), + keyword( + arg='Trie', + value=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork', + ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='trie')], + keywords=[]), + attr='Trie', + ctx=Load())), + keyword( + arg='Bloom', + value=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork', + ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='fork_types')], + keywords=[]), + attr='Bloom', + ctx=Load())), + keyword( + arg='Header', + value=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork', + ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='blocks')], + keywords=[]), + attr='Header', + ctx=Load())), + keyword( + arg='Block', + value=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork', + ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='blocks')], + keywords=[]), + attr='Block', + ctx=Load())), + keyword( + arg='set_account', + value=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork', + ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='set_account', + ctx=Load())), + keyword( + arg='set_storage', + value=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork', + ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='set_storage', + ctx=Load())), + keyword( + arg='state_root', + value=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork', + ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[]), + attr='state_root', + ctx=Load())), + keyword( + arg='root', + value=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork', + ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='trie')], + keywords=[]), + attr='root', + ctx=Load())), + keyword( + arg='hex_to_address', + value=Attribute( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork', + ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='utils.hexadecimal')], + keywords=[]), + attr='hex_to_address', + ctx=Load()))]), + simple=1), + Expr( + value=Call( + func=Attribute( + value=Name(id='genesis', ctx=Load()), + attr='add_genesis_block', + ctx=Load()), + args=[ + Name(id='description', ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Load()), + Name(id='genesis_configuration', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='downloader', + ctx=Store())], + value=Call( + func=Name(id='BlockDownloader', ctx=Load()), + args=[ + Name(id='forks', ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='rpc_url', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='geth', + ctx=Load()), + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Name(id='genesis_configuration', ctx=Load()), + attr='timestamp', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='set_block', + ctx=Load()), + args=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=0)], + keywords=[]), + Attribute( + value=Name(id='genesis_configuration', ctx=Load()), + attr='timestamp', + ctx=Load())], + keywords=[]))], + orelse=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='set_block', + ctx=Load()), + args=[ + Name(id='persisted_block', ctx=Load()), + Name(id='persisted_block_timestamp', ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Name(id='persisted_block', ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=256)], + keywords=[])]), + body=[ + Assign( + targets=[ + Name(id='initial_blocks_length', ctx=Store())], + value=Name(id='persisted_block', ctx=Load()))], + orelse=[ + Assign( + targets=[ + Name(id='initial_blocks_length', ctx=Store())], + value=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=255)], + keywords=[]))]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='downloader', + ctx=Store())], + value=Call( + func=Name(id='BlockDownloader', ctx=Load()), + args=[ + Name(id='forks', ctx=Load()), + Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='rpc_url', + ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='geth', + ctx=Load()), + BinOp( + left=Name(id='persisted_block', ctx=Load()), + op=Sub(), + right=Name(id='initial_blocks_length', ctx=Load())), + Name(id='persisted_block_timestamp', ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='blocks', ctx=Store())], + value=List(elts=[], ctx=Load())), + For( + target=Name(id='_', ctx=Store()), + iter=Call( + func=Name(id='range', ctx=Load()), + args=[ + Name(id='initial_blocks_length', ctx=Load())], + keywords=[]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='blocks', ctx=Load()), + attr='append', + ctx=Load()), + args=[ + Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='downloader', + ctx=Load()), + attr='take_block', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='BlockChain', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='blocks', + value=Name(id='blocks', ctx=Load())), + keyword( + arg='state', + value=Name(id='state', ctx=Load())), + keyword( + arg='chain_id', + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='fetch_chain_id', + ctx=Load()), + args=[ + Name(id='state', ctx=Load())], + keywords=[]))]))])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='persist', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Save the block list, state and chain id to file.\n ')), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='persist', + ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Return()], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='debug', + ctx=Load()), + args=[ + Constant(value='persisting blocks and state...')], + keywords=[])), + Assign( + targets=[ + Name(id='state_mod', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='state_mod', ctx=Load()), + attr='set_metadata', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Load()), + attr='state', + ctx=Load()), + Constant(value=b'chain_id'), + Call( + func=Attribute( + value=Call( + func=Name(id='str', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Load()), + attr='chain_id', + ctx=Load())], + keywords=[]), + attr='encode', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Assign( + targets=[ + Name(id='start', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='time', ctx=Load()), + attr='monotonic', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='state_mod', ctx=Load()), + attr='commit_db_transaction', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='state_mod', ctx=Load()), + attr='begin_db_transaction', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Load()), + attr='state', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='end', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='time', ctx=Load()), + attr='monotonic', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='info', + ctx=Load()), + args=[ + Constant(value='persisted state and %d blocks (took %.3f)'), + Call( + func=Name(id='len', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Load()), + attr='blocks', + ctx=Load())], + keywords=[]), + BinOp( + left=Name(id='end', ctx=Load()), + op=Sub(), + right=Name(id='start', ctx=Load()))], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='fetch_chain_id', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='state', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Fetch the persisted chain id from the database.\n ')), + Assign( + targets=[ + Name(id='state_mod', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[])), + Assign( + targets=[ + Name(id='chain_id', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='state_mod', ctx=Load()), + attr='get_metadata', + ctx=Load()), + args=[ + Name(id='state', ctx=Load()), + Constant(value=b'chain_id')], + keywords=[])), + If( + test=Compare( + left=Name(id='chain_id', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='chain_id', ctx=Store())], + value=Call( + func=Name(id='U64', ctx=Load()), + args=[ + Call( + func=Name(id='int', ctx=Load()), + args=[ + Name(id='chain_id', ctx=Load())], + keywords=[])], + keywords=[]))], + orelse=[]), + Return( + value=Name(id='chain_id', ctx=Load()))], + decorator_list=[], + returns=Name(id='U64', ctx=Load())), + FunctionDef( + name='process_blocks', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self')], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Validate blocks that have been fetched.\n ')), + Assign( + targets=[ + Name(id='time_of_last_commit', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='time', ctx=Load()), + attr='monotonic', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='gas_since_last_commit', ctx=Store())], + value=Constant(value=0)), + AnnAssign( + target=Name(id='last_committed_block', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='int', ctx=Load()), + ctx=Load()), + value=Constant(value=None), + simple=1), + AnnAssign( + target=Name(id='block', ctx=Store()), + annotation=Subscript( + value=Name(id='Optional', ctx=Load()), + slice=Name(id='Any', ctx=Load()), + ctx=Load()), + value=Constant(value=None), + simple=1), + FunctionDef( + name='persist', + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Nonlocal( + names=[ + 'time_of_last_commit']), + Nonlocal( + names=[ + 'gas_since_last_commit']), + Nonlocal( + names=[ + 'last_committed_block']), + Assign( + targets=[ + Name(id='now', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='time', ctx=Load()), + attr='monotonic', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Name(id='elapsed', ctx=Store())], + value=BinOp( + left=Name(id='now', ctx=Load()), + op=Sub(), + right=Name(id='time_of_last_commit', ctx=Load()))), + Assign( + targets=[ + Name(id='time_of_last_commit', ctx=Store())], + value=Name(id='now', ctx=Load())), + If( + test=Compare( + left=Name(id='elapsed', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=0)]), + body=[ + Assign( + targets=[ + Name(id='elapsed', ctx=Store())], + value=Constant(value=1))], + orelse=[]), + Assign( + targets=[ + Name(id='m_gas', ctx=Store())], + value=BinOp( + left=Name(id='gas_since_last_commit', ctx=Load()), + op=Div(), + right=Constant(value=1000000.0))), + Assign( + targets=[ + Name(id='m_gas_per_second', ctx=Store())], + value=BinOp( + left=Name(id='m_gas', ctx=Load()), + op=Div(), + right=Name(id='elapsed', ctx=Load()))), + Assign( + targets=[ + Name(id='gas_since_last_commit', ctx=Store())], + value=Constant(value=0)), + If( + test=Compare( + left=Name(id='block', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='count', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load())), + If( + test=Compare( + left=Name(id='last_committed_block', ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + AugAssign( + target=Name(id='count', ctx=Store()), + op=Sub(), + value=Name(id='last_committed_block', ctx=Load()))], + orelse=[]), + Assign( + targets=[ + Name(id='last_committed_block', ctx=Store())], + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load())), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='info', + ctx=Load()), + args=[ + Constant(value='imported chain segment count=%d mgas=%f mgasps=%f block=%d'), + Name(id='count', ctx=Load()), + Name(id='m_gas', ctx=Load()), + Name(id='m_gas_per_second', ctx=Load()), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='persist', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + While( + test=Constant(value=True), + body=[ + Assign( + targets=[ + Name(id='block', ctx=Store())], + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='downloader', + ctx=Load()), + attr='take_block', + ctx=Load()), + args=[], + keywords=[])), + If( + test=Compare( + left=Name(id='block', ctx=Load()), + ops=[ + Is()], + comparators=[ + Constant(value=None)]), + body=[ + Break()], + orelse=[]), + Try( + body=[ + Expr( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='process_block', + ctx=Load()), + args=[ + Name(id='block', ctx=Load())], + keywords=[]))], + handlers=[ + ExceptHandler( + type=Name(id='Exception', ctx=Load()), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='exception', + ctx=Load()), + args=[ + Constant(value='failed to process block %d'), + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load())], + keywords=[])), + Raise()])], + orelse=[], + finalbody=[]), + AugAssign( + target=Name(id='gas_since_last_commit', ctx=Store()), + op=Add(), + value=Constant(value=30000)), + AugAssign( + target=Name(id='gas_since_last_commit', ctx=Store()), + op=Add(), + value=Call( + func=Name(id='int', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='gas_used', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='persist', + ctx=Load()), + ops=[ + IsNot()], + comparators=[ + Constant(value=None)]), + body=[ + Assign( + targets=[ + Name(id='state_mod', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='state')], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='state_mod', ctx=Load()), + attr='set_metadata', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Load()), + attr='state', + ctx=Load()), + Constant(value=b'block_number'), + Call( + func=Attribute( + value=Call( + func=Name(id='str', ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load())], + keywords=[]), + attr='encode', + ctx=Load()), + args=[], + keywords=[])], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='state_mod', ctx=Load()), + attr='set_metadata', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Load()), + attr='state', + ctx=Load()), + Constant(value=b'block_timestamp'), + Call( + func=Attribute( + value=Call( + func=Name(id='str', ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load())], + keywords=[]), + attr='encode', + ctx=Load()), + args=[], + keywords=[])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='debug', + ctx=Load()), + args=[ + Constant(value='block %d applied'), + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load())], + keywords=[])), + If( + test=Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='stop_at', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='persist', ctx=Load()), + args=[], + keywords=[])), + Return()], + orelse=[]), + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2220000)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2463000)], + keywords=[])])]), + body=[ + If( + test=Compare( + left=Name(id='gas_since_last_commit', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='gas_per_commit', + ctx=Load()), + op=Div(), + right=Constant(value=10))]), + body=[ + Expr( + value=Call( + func=Name(id='persist', ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + orelse=[ + If( + test=BoolOp( + op=And(), + values=[ + Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load()), + ops=[ + Gt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2675000)], + keywords=[])]), + Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load()), + ops=[ + Lt()], + comparators=[ + Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=2700598)], + keywords=[])])]), + body=[ + If( + test=Compare( + left=Name(id='gas_since_last_commit', ctx=Load()), + ops=[ + Gt()], + comparators=[ + BinOp( + left=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='gas_per_commit', + ctx=Load()), + op=Div(), + right=Constant(value=10))]), + body=[ + Expr( + value=Call( + func=Name(id='persist', ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + orelse=[ + If( + test=Compare( + left=Name(id='gas_since_last_commit', ctx=Load()), + ops=[ + Gt()], + comparators=[ + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='options', + ctx=Load()), + attr='gas_per_commit', + ctx=Load())]), + body=[ + Expr( + value=Call( + func=Name(id='persist', ctx=Load()), + args=[], + keywords=[]))], + orelse=[])])])], + orelse=[])], + decorator_list=[], + returns=Constant(value=None)), + FunctionDef( + name='process_block', + args=arguments( + posonlyargs=[], + args=[ + arg(arg='self'), + arg( + arg='block', + annotation=Name(id='Any', ctx=Load()))], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Process a single block.\n ')), + If( + test=BoolOp( + op=Or(), + values=[ + Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='advance_block', + ctx=Load()), + args=[ + Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='timestamp', + ctx=Load())], + keywords=[]), + Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value=1)])]), + body=[ + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='debug', + ctx=Load()), + args=[ + Constant(value='applying %s fork...'), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork', + ctx=Load()), + attr='name', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='start', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='time', ctx=Load()), + attr='monotonic', + ctx=Load()), + args=[], + keywords=[])), + Assign( + targets=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Store())], + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='apply_fork', + ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Load())], + keywords=[])), + Assign( + targets=[ + Name(id='end', ctx=Store())], + value=Call( + func=Attribute( + value=Name(id='time', ctx=Load()), + attr='monotonic', + ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='info', + ctx=Load()), + args=[ + Constant(value='applied %s fork (took %.3f)'), + Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='active_fork', + ctx=Load()), + attr='name', + ctx=Load()), + BinOp( + left=Name(id='end', ctx=Load()), + op=Sub(), + right=Name(id='start', ctx=Load()))], + keywords=[]))], + orelse=[]), + Assert( + test=BoolOp( + op=Or(), + values=[ + UnaryOp( + op=Not(), + operand=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Load()), + attr='blocks', + ctx=Load())), + Compare( + left=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load()), + ops=[ + Eq()], + comparators=[ + BinOp( + left=Attribute( + value=Attribute( + value=Subscript( + value=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Load()), + attr='blocks', + ctx=Load()), + slice=UnaryOp( + op=USub(), + operand=Constant(value=1)), + ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + op=Add(), + right=Call( + func=Name(id='Uint', ctx=Load()), + args=[ + Constant(value=1)], + keywords=[]))])])), + If( + test=Compare( + left=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + ops=[ + NotEq()], + comparators=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load())]), + body=[ + Raise( + exc=Call( + func=Name(id='Exception', ctx=Load()), + args=[ + JoinedStr( + values=[ + Constant(value='expected block '), + FormattedValue( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load()), + conversion=-1), + Constant(value=' but got '), + FormattedValue( + value=Attribute( + value=Attribute( + value=Name(id='block', ctx=Load()), + attr='header', + ctx=Load()), + attr='number', + ctx=Load()), + conversion=-1)])], + keywords=[]))], + orelse=[]), + Expr( + value=Call( + func=Attribute( + value=Attribute( + value=Name(id='self', ctx=Load()), + attr='log', + ctx=Load()), + attr='debug', + ctx=Load()), + args=[ + Constant(value='applying block %d...'), + Attribute( + value=Name(id='self', ctx=Load()), + attr='block_number', + ctx=Load())], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Call( + func=Attribute( + value=Name(id='self', ctx=Load()), + attr='module', + ctx=Load()), + args=[ + Constant(value='fork')], + keywords=[]), + attr='state_transition', + ctx=Load()), + args=[ + Attribute( + value=Name(id='self', ctx=Load()), + attr='chain', + ctx=Load()), + Name(id='block', ctx=Load())], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None))], + decorator_list=[]), + FunctionDef( + name='main', + args=arguments( + posonlyargs=[], + args=[], + kwonlyargs=[], + kw_defaults=[], + defaults=[]), + body=[ + Expr( + value=Constant(value='\n Using an RPC provider, fetch each block and validate it.\n ')), + Expr( + value=Call( + func=Attribute( + value=Name(id='logging', ctx=Load()), + attr='basicConfig', + ctx=Load()), + args=[], + keywords=[ + keyword( + arg='level', + value=Attribute( + value=Name(id='logging', ctx=Load()), + attr='INFO', + ctx=Load()))])), + Assign( + targets=[ + Name(id='sync', ctx=Store())], + value=Call( + func=Name(id='Sync', ctx=Load()), + args=[], + keywords=[])), + Expr( + value=Call( + func=Attribute( + value=Name(id='sync', ctx=Load()), + attr='process_blocks', + ctx=Load()), + args=[], + keywords=[]))], + decorator_list=[], + returns=Constant(value=None)), + If( + test=Compare( + left=Name(id='__name__', ctx=Load()), + ops=[ + Eq()], + comparators=[ + Constant(value='__main__')]), + body=[ + Expr( + value=Call( + func=Name(id='main', ctx=Load()), + args=[], + keywords=[]))], + orelse=[])], + type_ignores=[]) \ No newline at end of file diff --git a/coq/ethereum_spec_tools/sync.v b/coq/ethereum_spec_tools/sync.v new file mode 100644 index 0000000000..7b9900af95 --- /dev/null +++ b/coq/ethereum_spec_tools/sync.v @@ -0,0 +1,25 @@ +(* Generated *) +(* +Ethereum Sync +^^^^^^^^^^^^^ + +Using an RPC provider, fetch each block and validate it with the specification. +*) + + +Definition main : M unit := + (* + Using an RPC provider, fetch each block and validate it. + *) + do* [[ M.get_field ~(| M.get_local ~(| "logging" |), "basicConfig" |) ~(| + + |) ]] in + do* M.assign "sync" [[ + M.get_local ~(| "Sync" |) ~(| + + |) in + ]] in + do* [[ M.get_field ~(| M.get_local ~(| "sync" |), "process_blocks" |) ~(| + + |) ]] in + M.pure tt. diff --git a/coq/translate.py b/coq/translate.py new file mode 100644 index 0000000000..3304eb72fa --- /dev/null +++ b/coq/translate.py @@ -0,0 +1,194 @@ +""" +Translate the Python source code of the EVM to Coq +""" +import ast +from dataclasses import dataclass, replace +from pathlib import Path +from typing import Literal + + +source_root_dir = Path("../src") + + +def indent(text: str) -> str: + levels = 2 + return "\n".join( + ( + " " * levels + line + if line.strip() != "" + else line + ) + for line in text.splitlines() + ) + + +@dataclass(frozen=True) +class Environment: + import_aliases: dict[str, str] + local_variables: set[str] + + +def to_coq_expression(environment: Environment, node: ast.expr) -> str: + if isinstance(node, ast.Attribute): + return \ + "M.get_field ~(| " + \ + to_coq_expression(environment, node.value) + ", " + \ + "\"" + node.attr + "\"" + \ + " |)" + if isinstance(node, ast.Call): + return \ + to_coq_expression(environment, node.func) + " ~(|\n" + \ + indent( + ',\n'.join(to_coq_expression(environment, arg) for arg in node.args) + ) + "\n" + \ + "|)" + if isinstance(node, ast.Constant): + if node.value is None: + return "tt" + if isinstance(node.value, int): + return str(node.value) + return "(* TODO constant *)" + if isinstance(node, ast.Name): + if node.id in environment.import_aliases: + return environment.import_aliases[node.id] + "." + node.id + if node.id in environment.local_variables: + return node.id + return "M.get_local ~(| \"" + node.id + "\" |)" + return "(* TODO expression *)" + + +def to_coq_statement(environment: Environment, node: ast.stmt) -> str: + if isinstance(node, ast.Expr): + if isinstance(node.value, ast.Constant): + return f"(*{node.value.value}*)" + return \ + "do* [[ " + to_coq_expression(environment, node.value) + " ]] in" + if isinstance(node, ast.Assign): + if len(node.targets) != 1: + return "(* TODO multiple assignment *)" + if isinstance(node.targets[0], ast.Name): + return \ + "do* M.assign \"" + node.targets[0].id + "\" [[\n" + \ + indent( + to_coq_expression(environment, node.value) + " in" + ) + "\n" +\ + "]] in" + return "(* TODO assignment *)" + if isinstance(node, ast.AugAssign): + return \ + "do* M.aug_assign " + \ + "[[ " + to_coq_expression(environment, node.target) + " ]] [[\n" + \ + indent( + to_coq_expression(environment, node.value) + ) + "\n" +\ + "]] in" + return "(* TODO statement *)" + + +def to_coq_type(environment: Environment, node: ast.expr) -> str: + if isinstance(node, ast.Name): + return node.id + if isinstance(node, ast.Constant): + if node.value is None: + return "unit" + return "(* TODO constant type *)" + return "(* TODO type *)" + + +def to_coq_function_def(environment: Environment, node: ast.FunctionDef) -> str: + arguments = "".join( + " (" + arg.arg + " : " + to_coq_type(environment, arg.annotation) + ")" + for arg in node.args.args + if arg.annotation is not None + ) + local_variables: set[str] = set(arg.arg for arg in node.args.args) + return_type = \ + to_coq_type(environment, node.returns) \ + if node.returns is not None \ + else "unit" + output = f"Definition {node.name}{arguments} : M {return_type} :=\n" + + local_environment = replace(environment, local_variables=local_variables) + for statement in node.body: + output += indent(to_coq_statement(local_environment, statement)) + "\n" + output += indent("M.pure tt.") + + return output + + +def dir_parent_n_times(dir_path: Path, n: int) -> Path: + for _ in range(n): + dir_path = dir_path.parent + return dir_path + + +ToCoqMode = Literal['header_comment', 'imports', 'definitions'] + + +def to_coq(dir_path: Path, tree: ast.AST) -> str: + if isinstance(tree, ast.Module): + output = "(* Generated *)\n" + mode: ToCoqMode = 'header_comment' + environment: Environment = Environment( + import_aliases={}, + local_variables=set() + ) + + for node in tree.body: + if mode == 'header_comment': + if isinstance(node, ast.Expr) and isinstance(node.value, ast.Constant): + output += f"(*{node.value.value}*)\n\n" + mode = 'imports' + continue + else: + return "No description available at the beginning of the file" + if mode == 'imports': + if isinstance(node, ast.ImportFrom): + module = node.module if node.module is not None else "__init__" + for alias in node.names: + environment.import_aliases[alias.name] = module + prefix = ( + str(dir_parent_n_times( + dir_path.relative_to(source_root_dir), + node.level - 1, + )).replace("/", ".") + "." + if node.level != 0 + else "" + ) + output += f"Require {prefix}{module}.\n" + else: + mode = 'definitions' + if isinstance(node, ast.FunctionDef): + output += '\n' + output += to_coq_function_def(environment, node) + "\n" + + return output + + return "Expected a Module node at top-level" + + +def to_ast(tree: ast.AST) -> str: + return ast.dump(tree, indent=4) + + +def translate_file(file_path: Path) -> None: + with open(file_path) as f: + source = f.read() + tree = ast.parse(source) + output_file_path = file_path.relative_to(source_root_dir) + + # Create the output directory if it does not exist + output_file_path.parent.mkdir(parents=True, exist_ok=True) + + # Output the AST file + with open(output_file_path.with_suffix(".ast"), "w") as f: + f.write(ast.dump(tree, indent=4)) + + # Output the Coq file + with open(output_file_path.with_suffix(".v"), "w") as f: + f.write(to_coq(file_path.parent, tree)) + + +# We iterate over all the files in the source directory, recursively +for file_path in source_root_dir.rglob("*.py"): + translate_file(file_path)